Subject address: Github
Online editor: TypeScript Playground
1. ReturnType
type MyReturnType<Fn extends Function> = Fn extends(... args:any) => infer R ? R : never;
Copy the code
2. Omit
type MyExclude<T, K> = T extends K ? never : T;
type MyOmit<T, K extends keyof T> = {
[P in MyExclude<keyof T, K>]: T[P];
}
Copy the code
3. Readonly2
Allows you to select the specified key for readonly
type MyReadonly2<T, K extends keyof T> = {
readonly [P in K]: T[P];
} & {
[P in MyExclude<keyof T, K>]: T[P];
}
Copy the code
4. DeepReadonly
Readonly nested properties as well
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends number | string | symbol ? T[P] : DeepReadonly<T[P]>;
}
Copy the code
Types can also be recursive
5. TupleToUnion
type TupleToUnion<A extends any[]> = A[number]
Copy the code
6. Chainable
Implementation can be called chain type structure, including option(key, value) get() two methods, the parameters of option is the property and value of the object, get used to get the final result.
The main thing is to implement type declarations that do this without writing logic
interface Chainable<T = {}> {
// 'K extends String' Narrows the 'key' type to a literal type when it is derived by TS
// '[P in K]' is used to derive 'K' as a union type, and then use 'in' to get the specific type, used as
// the key name, so that the final type has an explicit key name
option: <K extends string, V>(key: K, value: V) => Chainable<T & {
[P in K]: typeof value
}>,
get: () => T
}
Copy the code
Being able to call chained means that the option method returns this type, so we need to provide a generic parameter T that does this: 1. Receives the key value passed by repeated calls to option and constructs a new type to continue as the next T; 2. Return value as get method.
7. Last
Gets the type of the last value of the array
type Last<A extends any[] = > [undefined. A][A['length']].Copy the code
I didn’t get it. I didn’t turn it around. The clever idea is to add an element to the front of the array, so that the original length is the last index of the new array
8. Pop
Implement the pop method of the array, return the array type after the POP
type Pop<A extends any[]> = A extends [...infer R, infer L] ? R : undefined;
type Shift<A extends any[]> = A extends [infer F, ...infer R] ? R : undefined;
Copy the code
The shift in the same way
Last could be used in a similar way, for example by returning L directly. It is important to note that the infer keyword must be used after extends in the condition type
9. PromiseAll
Take the type of the value returned by promise.all ()
type GetPromiseType<P> = P extends Promise<infer R> ? R : P;
type PromiseAll<P extends any[], R extends any[] = []> = P extends [infer F, ...infer Rest]
? PromiseAll<Rest, [GetPromiseType<F>, ...R]>
: Promise<R>;
Copy the code
Again, recursion. I haven’t thought of any other way yet. To get the type of each item, recurse to the first element
10. LookUp
Find the correct type from the union type (there is {type: string} in the qualified type)
type LookUp<T, P> = T extends { type: P } ? T : never;
Copy the code
‘a’ | never = = = ‘a’, and any other types and | never returns to its itself
11. TrimLeft
Trim left on the string
type TrimLeft<S extends string> = S extends `${infer F}${infer R}`
? F extends ' '
? TrimLeft<R>
: S
: S;
Copy the code
Strings can also be deconstructed using conditional types, one character at a time. Strings can be freely deconstructed according to reasonable patterns
12. Trim
type ReverseString<
S extends string,
R extends string = ' '
> = S extends `${infer F}${infer Rest}`
? ReverseString<Rest, `${F}${R}`>
: R;
type Trim<S extends string> = ReverseString<TrimLeft<ReverseString<TrimLeft<S>>>>
Copy the code
The idea is to trim the lefe, flip it, trim the left, and flip it back