TypeScript | Type Challenges
Implement the built-in Pick<T, K> generic without using it.
// type MyPick<T, K> = K extends keyof T ? { [P in K]: T[P] } : {}
type MyPick<T, K extends keyof T> = { [P in K]: T[P] }
Implement the built-in Readonly<T> generic without using it.
type MyReadonly<T> = {
readonly [P in keyof T]: T[P]
}
Given an array, transform to a object type and the key/value must in the given array.
type TupleToObject<T extends readonly any[]> = {
[K in T[number]]: K
}
Implement a generic First that takes an Array T and returns it's first element's type.
type First<T extends any[]> = T extends [infer A, ...any] ?
A : never
For given a tuple, you need create a generic Length, pick the length of the tuple.
type Length<T extends readonly any[]> = T["length"]
Implement the built-in Exclude<T, U>.
type MyExclude<T, U> = T extends U ? never : T
If we have a type which is wrapped type like Promise. How we can get a type which is inside the wrapped type? For example if we have Promise<ExampleType> how to get ExampleType?
type Awaited<T> = T extends Promise<infer R> ? R : never
Implement a utils If which accepts condition C, a truthy return type T, and a falsy return type F. C is expected to be either true or false while T and F can be any type.
type If<C extends true | false, T, F> = C extends true ? T : F
Implement the JavaScript Array.concat function in the type system. A type takes the two arguments. The output should be a new array that includes inputs in ltr order
type Concat<T extends any[], U extends any[]> = [...T, ...U]
Implement the JavaScript Array.includes function in the type system. A type takes the two arguments. The output should be a boolean true or false.
type Includes<T extends readonly any[], U> = U extends T[number] ? true : false
Implement the built-in ReturnType<T> generic without using it.
type MyReturnType<T> = T extends (..._: any[]) => infer R ? R : never
Implement the built-in Omit<T, K> generic without using it.
type MyOmit<T, K> = Pick<T, Exclude<keyof T, K>>
Implement a generic MyReadonly2<T, K> which takes two type argument T and K.
K specify the set of properties of T that should set to Readonly. When K is not provided, it should make all properties readonly just like the normal Readonly<T>.
type Flatten<T extends { [key: string]: any }> = { [key in keyof T]: T[key] }
type MyReadonly2<T, K extends keyof T = keyof T> = Flatten<T & { readonly [S in K]: T[S] }>
Implement a generic DeepReadonly<T> which make every parameter of an object - and its sub-objects recursively - readonly.
type DeepReadonly<T> = keyof T extends never ? T : { readonly [P in keyof T]: DeepReadonly<T[P]> }
Implement a generic TupleToUnion<T> which covers the values of a tuple to its values union.
type TupleToUnion<T extends any[]> = T extends [_: infer H, ..._: infer Rest] ? (H | TupleToUnion<Rest>) : never
Implement an object to provide two function option(key, value) and get()
- In
option, you can extend the current config type by the given key and value. - We should about to access the final config type via
get.
type Flatten<T extends Record<string, any>> = { [key in keyof T]: T[key] }
type Extend<O extends Record<string, any>, K extends string, T> = Flatten<O & { [S in K]: T }>
type Chainable<Options = {}> = {
option<K extends string, T>(key: K, value: T): Chainable<Extend<Options, K, T>>
get(): Options
}
Implement a generic Last<T> that takes an Array T and returns it's last element's type.
type Last<T extends any[]> = T extends [...any, infer A] ? A : never
Implement a generic Pop<T> that takes an Array T and returns an Array without it's last element.
type Pop<T extends any[]> = T extends [...infer A, any] ? A : never
Type the function PromiseAll that accepts an array of PromiseLike objects, the returning value should be Promise<T> where T is the resolved result array.
type Awaited<T> = T extends PromiseLike<infer U> ? U : T;
declare function PromiseAll<T extends any[]>(values: readonly [...T]): Promise<{
[P in keyof T]: Awaited<T[P]>
}>