TypeScript Challenges 总结
常用方法
Concat
type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U];
Includes
type Includes<T extends unknown[], U> = T extends [infer F, ...infer R]
? Equal<F, U> extends true
? true
: Includes<R, U>
: false;
ReadonlyPart
type ReadonlyPart<
T extends Record<any, unknown>,
K extends keyof T = keyof T
> = Omit<T, K> & Readonly<Pick<T, K>>;
DeepReadonly
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends Record<any, any>
? T[K] extends Function
? T[K]
: DeepReadonly<T[K]>
: T[K];
};
TupleLength
type TupleLength<T extends unknown[]> = T extends { length: infer P }
? P
: never;
Split
type Split<S extends string, SEP extends string = ''> = string extends S
? string[]
: S extends `${infer L}${SEP}${infer R}`
? [L, ...(R extends '' ? [] : Split<R, SEP>)]
: SEP extends ''
? []
: [S];
RemoveIndexSignature
type RemoveIndexSignature<T, P = PropertyKey> = {
[K in keyof T as P extends K ? never : K extends P ? K : never]: T[K];
};
Reverse
type Reverse<T extends any[]> = T extends [infer L, ...infer R]
? [...Reverse<R>, L]
: T;
ConstructTuple
type ConstructTuple<
L extends number,
U extends any[] = []
> = 0 extends 1
? false
: U['length'] extends L
? U
: ConstructTuple<L, [...U, unknown]>;
DeepMutable
type DeepMutable<T extends object> = T extends object
? {
-readonly [K in keyof T]: T[K] extends object
? T[K] extends Function
? T[K]
: DeepMutable<T[K]>
: T[K];
}
: T;
GetRequired
type GetRequired<T> = {
[K in keyof T as T[K] extends Required<T>[K] ? K : never]: T[K];
};
GetOptional
type GetOptional<T> = {
[K in keyof T as { [P in K]: T[K] } extends { [P in K]-?: T[K] }
? never
: K]: T[K];
};
Equal
export type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
? true
: false;
LiteralUnion
export type LiteralUnion<T extends string> = T | (string & {});
Flatten
type Flatten<T> = {
[K in keyof T]: T[K] extends object ? Flatten<T[K]> : T[K]
}
类型的转换
TupleToObject
type TupleToObject<T extends readonly PropertyKey[]> = {
[K in T[number]]: K;
};
TupleToUnion
type TupleToUnion<T extends unknown[]> = T[number];
UnionToIntersection
type UnionToIntersection<T> = (
T extends any ? (args: T) => unknown : never
) extends (args: infer U) => unknown
? U
: never;
UnionToTuple
type UnionToIntersection<T> = (T extends T ? (x: T) => 0 : never) extends (
x: infer P
) => 0
? P
:never;
type LastInUnion<T> = UnionToIntersection<
T extends T ? (x: T) => 0 : never
> extends (x: infer P) => 0
? P
: never;
type UnionToTuple<T, Last = LastInUnion<T>> = [T] extends [never]
? []
: [...UnionToTuple<Exclude<T, Last>>, Last]
类型判断
IsNever
type IsNever<T> = [T] extends [never] ? true :false;
IsUnion
type IsUnion<T, U = T> = (
T extends T ? (U extends T ? true : unknown) : never
) extends true
? false
: true;
IsTuple
type IsTuple<T> = [T] extends [never]
? false
: T extends readonly any[]
? number extends T['length']
? false
: true
: false;
IsAny
type IsAny<T> = 0 extends 1 & T ? true : false;