Scarlet Serenade

TypeScript | Type Challenges

https://github.com/type-challenges/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

playground


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

playground


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]

playground


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

playground


Implement the built-in ReturnType<T> generic without using it.

type MyReturnType<T> = T extends (..._: any[]) => infer R ? R : never

playground


Implement the built-in Omit<T, K> generic without using it.

type MyOmit<T, K> = Pick<T, Exclude<keyof T, K>>

playground


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] }>

playground


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]> }

playground


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

playground


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
}

playground


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

playground


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

playground


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]>
}>

playground