上难度,直接看 github 上的项目
https://github.com/type-challenges/type-challenges

Pick

1
2
3
4
5
6
7
8
9
10
11
12
interface Todo {
title: string
description: string
completed: boolean
}

type TodoPreview = MyPick<Todo, 'title' | 'completed'>

const todo: TodoPreview = {
title: 'Clean room',
completed: false,
}
1
2
3
type MyPick<T, K extends keyof T> = {
[P in K]: T[P]
}

Parameters

1
2
3
const foo = (arg1: string, arg2: number): void => {}

type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]
1
2
3

type MyParameters<T extends (...args: any[]) => any> = T extends (...any: infer S) => any ? S : any

Awaited

1
2
3
type ExampleType = Promise<string>

type Result = MyAwaited<ExampleType> // string
1
2
3
4
5
6
7
type Thenable<T> = {
then: (onfulfilled: (arg: T) => unknown) => unknown;
}

type MyAwaited<T extends Thenable<any> | Promise<any>> = T extends Promise<infer Inner>
? Inner extends Promise<any> ? MyAwaited<Inner> : Inner
: T extends Thenable<infer U> ? U : false

Zip

1
type exp = Zip<[1, 2], [true, false]> // expected to be [[1, true], [2, false]]
1
2
3
type Zip<A extends any[], B extends any[], L extends any[] = []> = L['length'] extends A['length'] | B['length']
? L
: Zip<A, B, [...L, [A[L['length']], B[L['length']]]]>

IsTuple

1
2
3
type case1 = IsTuple<[number]> // true
type case2 = IsTuple<readonly [number]> // true
type case3 = IsTuple<number[]> // false
1
2
3
4
type IsTuple<T> = 
T extends readonly any[]?
number extends T['length']?false:true
:false

Join

1
2
3
4
type Res = Join<["a", "p", "p", "l", "e"], "-">; // expected to be 'a-p-p-l-e'
type Res1 = Join<["Hello", "World"], " ">; // expected to be 'Hello World'
type Res2 = Join<["2", "2", "2"], 1>; // expected to be '21212'
type Res3 = Join<["o"], "u">; // expected to be 'o'
1
2
3
4
5
type Join<T extends any[], U extends string | number> = T extends [infer F, ...infer R]
? R['length'] extends 0
? `${F & string}`
: `${F & string}${U}${Join<R, U>}`
: never