1、实现 Get Return Type
题目内容
题目解析
涉及知识点: infer
这题就很简单了,我们只要返回函数最终的返回值类型就好了。
使用 infer 推断函数返回的类型,有就有,没有就是never。
题目答案
// ============= Your Code Here =============
type MyReturnType<T> = T extends (...args: any[]) => infer P ? P : never
2、实现 Omit
题目内容
题目解析
涉及知识点: keyof 、 extends
本题主要就是剔除一些不需要的属性,因此需要注意几点:
-
K是要剔除的属性,肯定是T的属性中的,所以 K extends keyof T;
-
需要剔除K中列出的属性,只需要在返回的属性 keyod T 中过滤掉K中列出的属性即可 [P in Exclude<keyof T, K>].
题目答案
// ============= Your Code Here =============
type Exclude<T, U> = T extends U ? never : T
type MyOmit<T, K extends keyof T> = {
[P in Exclude<keyof T, K>] : T[P]
}
3、实现 Readonly 2
题目内容
题目解析
涉及知识点: keyof 、 as
easy难度的时候,已经有过一篇关于readonly的题目,忘记的可自行查看。
本题呢则是增加了一点点难度,就是给部分属性增加readonly。
那么就简单了,我们只需要给需要的增加readonly,也就是属于K 里的都需要是readonly,不属于K里的都不是。
as P extends K ? P : never, 这里增加as是为了过滤,已经存在过的就不需要再次判断了。
题目答案
// ============= Your Code Here =============
type MyReadonly2<T, K extends keyof T = keyof T> = {
[P in keyof T as P extends K ? never: P] : T[P]
} & {
readonly [P in keyof T as P extends K ? P : never] : T[P]
}
4、实现 Deep Readonly
题目内容
For example:
type X = {
x: {
a: 1
b: 'hi'
}
y: 'hey'
}
type Expected = {
readonly x: {
readonly a: 1
readonly b: 'hi'
}
readonly y: 'hey'
}
type Todo = DeepReadonly<X> // should be same as `Expected`
题目解析
涉及知识点: keyof 、 readonly
与上题也是关于readonly的。前面也说了,easy难度的时候,已经有过一篇关于readonly的题目,忘记的可自行查看。
本题其实就是基于easy的难度readonly,增加一个判断,如果T[K] 返回依然是个对象,那就继续深度遍历下去。
如何判别返回的是不是个对象呢?只要判断 T[K] 还有没有属性名即可,keyof T[K] extends never。
题目答案
// ============= Your Code Here =============
type DeepReadonly<T> = {
readonly [K in keyof T] : keyof T[K] extends never ? T[K] : DeepReadonly<T[K]>
}
5、实现 Tuple to Union
题目内容
题目解析
涉及知识点: Tuple
我觉得这题不需要解析了。。。
题目答案
// ============= Your Code Here =============
type TupleToUnion<T extends any[]> = T[number]
6、实现 Chainable Options
题目内容
For example:
declare const config: Chainable
const result = config
.option('foo', 123)
.option('name', 'type-challenges')
.option('bar', { value: 'Hello World' })
.get()
// expect the type of result to be:
interface Result {
foo: number
name: string
bar: {
value: string
}
}
你只需要在类型层面实现这个功能 - 不需要实现任何 TS/JS 的实际逻辑。
你可以假设 key 只接受字符串而 value 接受任何类型,你只需要暴露它传递的类型而不需要进行任何处理。同样的 key 只会被使用一次。
题目解析
涉及知识点: extends
其实就是实现一个Chainable, 有两个属性 option 和 get。
option就是不断的定义属性名和属性值,每一定义好的 key-value 都拼接到T中,形成一个对象;
get就是返回返回形成的这个对象 T 。
题目答案
// ============= Your Code Here =============
type Chainable<T = {}> = {
option<K extends string, V extends any>(key: K, value: V)
: Chainable<T & { [P in K] : V }>
get(): T
}
tips:
Medium级别的题目总共有75题,为了方便少量多次查看,缓解疲劳,我们就以6题为一篇进行。