interface Todo { title: string; description: string; completed: boolean;}type MyPick<T, K extends keyof T> = { [P in K]: T[P];};type TodoPreview = MyPick<Todo, 'title' | 'completed'>;const todo: TodoPreview = { title: 'Clean room', completed: false,};
interface Todo { title: string; description: string;}type MyReadonly<T> = { readonly [P in keyof T]: T[P];};const todo: MyReadonly<Todo> = { title: 'Hey', description: 'foobar',};todo.title = 'Hello'; // Error: cannot reassign a readonly propertytodo.description = 'barFoo'; // Error: cannot reassign a readonly property
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const;type TupleToObject<T extends readonly (string | number)[]> = { [X in T[number]]: X;};type result = TupleToObject<typeof tuple>; // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
type arr1 = ['a', 'b', 'c'];type arr2 = [3, 2, 1];type First<T extends any[]> = T[number] extends never ? never : T[0];// type First<T extends any[]> = T['length'] extends 0 ? never : T[0]type MyFirst<T extends unknown[]> = T extends [infer F, ...(infer R)] ? F : never;type head1 = First<arr1>; // expected to be 'a'type head2 = First<arr2>; // expected to be 3
type tesla = ['tesla', 'model 3', 'model X', 'model Y'];type spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'];type Length<T extends readonly any[]> = T['length'];type teslaLength = Length<tesla>; // expected 4type spaceXLength = Length<spaceX>; // expected 5
type MyExclude<T, K> = T extends K ? never : T;type Result = MyExclude<'a' | 'b' | 'c', 'a'>; // 'b' | 'c'
type ExampleType = Promise<string>type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer X> ? X extends Promise<unknown> ? MyAwaited<X> : X : never;type Result = MyAwaited<ExampleType> // string
type If<T extends boolean, A, B> = T extends true ? A : B;type A = If<true, 'a', 'b'>; // expected to be 'a'type B = If<false, 'a', 'b'>; // expected to be 'b'
type Concat<T extends any[], K extends any[]> = T extends [...(infer A)] ? K extends [...(infer B)] ? [...A, ...B] : never : never;type Concat<T extends any[], K extends any[]> = [...T, ...K];type Result = Concat<[1, 3], [2, 5]>; // expected to be [1, 3, 2, 5]
type IsEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;type Includes<T extends readonly any[], U> = T extends [infer R, ...infer Rest] ? true extends IsEqual<R, U> ? true : Includes<Rest, U> : false;type isPillarMen = Includes<["Kars", "Esidisi", "Wamuu", "Santana"], "Dio">; // expected to be `false`
type Push<T extends any[], K> = [...T, K];type Result = Push<[1, 2], '3'>; // [1, 2, '3']
type Unshift<T extends any[], K> = [K, ...T];type Result = Unshift<[1, 2], 0> // [0, 1, 2,]
const foo = (arg1: string, arg2: number): void => {};type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer R) => unknown ? [...R] : never;type FunctionParamsType = MyParameters<typeof foo>; // [arg1: string, arg2: number]
const fn = (v: boolean) => { if (v) return 1; else return 2;};type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R ? R : never;type a = MyReturnType<typeof fn>; // should be "1 | 2"
type Subsequence<T extends any[]> = T extends [infer F, ...(infer R)] ? [F, ...Subsequence<R>] | Subsequence<R> : [];type Subsequence<T extends any[], Prefix extends any[] = []> = T extends [infer F, ...(infer R)] ? Subsequence<R, Prefix | [...Prefix, F]> : Prefix;type A = Subsequence<[1, 2]>; // [] | [1] | [2] | [1, 2]
type Combination< // [foo, bar, baz], the original T, this won't be changed T extends string[], // foo | bar | baz > bar | baz > baz > ... need this because T[number] is fixed Unioned extends string = T[number], // foo | bar | baz > foo > ... for `Unioned extends Permutated ? never : Unioned` Permutated extends string = Unioned> = | Unioned // full union: foo | bar | baz | (Permutated extends any ? // [Permutation](https://github.com/type-challenges/type-challenges/issues/614) // Permutation will stop when Unioned is never // Permutation will loop each value and apply to the following // split it: `foo Combination<bar | baz>`, `foo` and `bar | baz` are mutually exclusive `${Permutated}${Combination< T, Unioned extends Permutated ? never : Unioned >}` : never);type Keys = Combination<["foo", "bar", "baz"]>;
type foo = { name: string; age: string;};type coo = { age: number; sex: string;};// type Merge<F, S> = {// [P in keyof F | keyof S]: P extends keyof S ? S[P] : P extends keyof F ? F[P] :never// }// type Merge<F, S> = {// [P in keyof (F & S)]: P extends keyof S ? S[P] : P extends keyof F ? F[P] :never// }type Merge<T, U> = Omit<Omit<T, keyof U> & U, never>;type Result = Merge<foo, coo>; // expected to be {name: string, age: number, sex: string}
type NodeA = { type: "A"; name: string; flag: number;};type NodeB = { type: "B"; id: number; flag: number;};type NodeC = { type: "C"; name: string; flag: number;};type Nodes = NodeA | NodeB | NodeC;type ReplacedNodes = ReplaceKeys< Nodes, "name" | "flag", { name: number; flag: string }>;// {type: 'A', name: number, flag: string} | {type: 'B', id: number, flag: string} | {type: 'C', name: number, flag: string} // would replace name from string to number, replace flag from number to string.type ReplacedNotExistKeys = ReplaceKeys<Nodes, "name", { aa: number }>;type ReplaceKeys< U, T extends PropertyKey, Y extends { [J in PropertyKey]: any; }> = U extends {} ? { [K in keyof U]: K extends keyof Y ? Y[K] : K extends T ? never : U[K]; } : never;
type Foo = { [key: string]: any; foo(): void;}type A = RemoveIndexSignature<Foo> // expected { foo(): void }type RemoveIndexSignature<T,K=keyof T> = { [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K]}type RemoveIndexSignature<T, P=PropertyKey> = { [K in keyof T as P extends K ? never : K extends P ? K : never]: T[K]}
type PString1 = "";type PString2 = "+85%";type PString3 = "-85%";type PString4 = "85%";type PString5 = "85";// type PercentageParser<// T extends string,// P extends string = '',// N extends string = '',// S extends string = ''> =// T extends `${infer A}${infer B}` ? A extends '+'|'-' ?// PercentageParser<B, A, N, S> : A extends '%' ?// PercentageParser<B, P, N, A> :// PercentageParser<B, P, `${N}${A}`, S> : [P, N, S];type Parser1<A extends string> = A extends `${infer H}${infer _}` ? H extends "-" | "+" ? H : "" : "";type Parser2<A extends string> = A extends `${infer _}%` ? "%" : "";type Parser3<A extends string> = A extends `${Parser1<A>}${infer M}${Parser2<A>}` ? M : "";type PercentageParser<A extends string> = [Parser1<A>, Parser3<A>, Parser2<A>];type R1 = PercentageParser<PString1>; // expected ['', '', '']type R2 = PercentageParser<PString2>; // expected ["+", "85", "%"]type R3 = PercentageParser<PString3>; // expected ["-", "85", "%"]type R4 = PercentageParser<PString4>; // expected ["", "85", "%"]type R5 = PercentageParser<PString5>; // expected ["", "85", ""]
// 题28interface User { name: string; age: number; address: string;}// type PartialByKeys<T, U extends keyof T> = {// []// }// type PartialByKeys<// T,// K=keyof T,// PartialOne = {[J in K & keyof T]?: T[J]|undefined},// RequiredOne = {[J in Exclude<keyof T,K>]: T[J]},// Intersection = PartialOne&RequiredOne,// > =// {[J in keyof Intersection]: Intersection[J]} ;type PartialByKeys<T, U extends keyof T> = Merge<Partial<T>, Omit<T, U>>;type UserPartialName = PartialByKeys<User, "name">; // { name?:string; age:number; address:string }// 题29type OmitByType<T, K> = { [P in keyof T as T[P] extends K ? never : P]: T[P];};type OmitBoolean = OmitByType< { name: string; count: number; isReadonly: boolean; isEnable: boolean; }, boolean>; // { name: string; count: number }// 题30// type Test = '123';// type StringToUnion<T> = T extends `${infer A}${infer R}` ? A | StringToUnion<R> : never;// type Result = StringToUnion<Test>; // expected to be "1" | "2" | "3"// 题31type GetOptional<T extends Record<string, unknown>> = { [K in keyof T as {} extends Pick<T, K> ? K : never]: T[K];};// type GetOptional<T> = {// [P in keyof T as T[P] extends Required<T>[P] ? never : P]: T[P]// }type I = GetOptional<{ foo: number; bar: string | undefined }>; // expected to be { bar?: string }type Test = {} extends Pick<{ foo: number; bar?: string }, "bar"> ? false : true;// 题32// type RequiredKeys<T extends object, P = keyof T> =// P extends keyof T ? T[P] extends Required<T>[P] ? P : never : never;// type Result = RequiredKeys<{ foo: number; bar?: string }>;// 题33type Foo = { a: string; b: number;};type Bar = { a: string; c: boolean;};// type Diff<A, B, K = keyof A & keyof B> = {// [P in keyof A | keyof B as P extends K ? never : P ]: P extends keyof A ? A[P] : P extends keyof B ? B[P] : never;// };type Diff<T, U> = Omit<T & U, keyof T & keyof U>;type Result1 = Diff<Foo, Bar>; // { b: number, c: boolean }type Result2 = Diff<Bar, Foo>; // { b: number, c: boolean }// 题34interface Model { name: string; age: number; locations?: string[] | null;}// 这里的infer Rest是除了undefined之外的值// type ObjectEntries<T, U = keyof T> =// U extends keyof T ? [U, T[U] extends infer Rest | undefined ? Rest : T[U]] : never;// -?是必选// type ObjectEntries<T> = {// [K in keyof T]-?: [K, [Exclude<T[K], undefined>] extends [never] ? undefined : Exclude<T[K], undefined>]// }[keyof T]// type ObjectEntries<T> = {// [key in keyof T]-?: [key, T[key] extends (infer R | undefined)? R: T[key]]// }[keyof T]type ObjectEntries< T extends object, K extends keyof T = keyof T> = K extends keyof T ? [K, Required<T>[K]] : never;type modelEntries = ObjectEntries<Model>;// 题35// type Flip<T extends Record<string, any>> = {// [K in keyof T as `${T[K]}`]: K// }// type t1 = Flip<{ a: "x", b: "y", c: "z" }>; // {x: 'a', y: 'b', z: 'c'}// type t2 = Flip<{ a: 1, b: 2, c: 3 }>; // {1: 'a', 2: 'b', 3: 'c'}// type t3 = Flip<{ a: false, b: true }>; // {false: 'a', true: 'b'}// 题36// const brand = {// 全部: 'ALL',// 本品: 'SELF',// 竞品: 'COMPETITION',// } as const;// type EnumOptions<T, K = keyof T> = K extends keyof T ? {label: K; value: T[K]}[] : never;// type s1 = EnumOptions<typeof brand>;// 题37// type TupleToNestedObject<T, U> = T extends [infer J extends string, ...infer K] ? Record<J, TupleToNestedObject<K, U>> : U// type TupleToNestedObject<T extends string[], U> =// T extends [infer K, ...infer Rest] ? K extends string// ? { [Key in K]: Rest extends string[] ? TupleToNestedObject<Rest, U> : U }// : never : U;// type a = TupleToNestedObject<['a'], string> // {a: string}// type b = TupleToNestedObject<['a', 'b'], number> // {a: {b: number}}// type c = TupleToNestedObject<[], boolean> // boolean. if the tuple is empty, just return the U type// 题38const tuple = ["tesla", "model 3", "model X", "model Y"] as const;type TupleToObject<T extends readonly any[]> = { [P in T[number]]: P;};type result = TupleToObject<typeof tuple>;// expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}// 题39// type DropChar<T extends string, U extends string> =// T extends string ? T extends `${infer A}${infer Rest}` ? `${U extends A ? "" : A}${DropChar<Rest, U>}` : '' : never;type DropChar< T extends string, U extends string> = T extends `${infer A}${U}${infer Rest}` ? DropChar<`${A}${Rest}`, U> : T;type Butterfly = DropChar<" b u t t e r f l y ! ", " ">; // 'butterfly!'// 题40type Union2Intersection<U> = ((x: U) => any) extends (x: infer I) => any ? I : undefined;type I1 = Union2Intersection<"foo" | 42 | true>;// 题41type Data = { foo: { bar: { value: "foobar"; count: 6; }; included: true; }; hello: "world";};// type Get<T, K extends string> =// K extends keyof T ? T[K] : K extends `${infer S}.${infer Rest}` ? S extends keyof T// ? Get<T[S], Rest> : never : never;// K & keyof T 的结果就是 K ,这里只是为了处理T[K]的报错type Get<T, K extends string> = K extends `${infer K}.${infer R}` ? Get<T[K & keyof T], R> : T[K & keyof T];type A = Get<Data, "hello">; // 'world'type B = Get<Data, "foo.bar.value">; // 6type C = Get<Data, "foo.bar">; // { value: 'foobar', count: 6 }// 题42type StringToNumber<N> = N extends `${infer T extends number}` ? T : never;type T2 = StringToNumber<"2">;// 题43[]// type FilterOut<T extends any[], K> =// T extends [infer A, ...infer Rest] ? A extends K ? never : FilterOut<Rest, K> : never;// type FilterOut<T extends any[], F, U extends any[] = []> = T extends [infer K, ...infer R]// ? [K] extends [F]// ? FilterOut<R, F, [...U]>// : FilterOut<R, F, [...U, K]>// : Utype FilterOut<T extends any[], U> = T extends [infer First, ...infer Rest] ? [First] extends [U] ? FilterOut<Rest, U> : [First, ...FilterOut<Rest, U>] : T;type Filtered = FilterOut<[1, 2, null, 3], null>; // [1, 2, 3]