类型体操-简单
[项目地址](type-challenges/README.zh-CN.md at main · type-challenges/type-challenges)很疯狂
实现 Pick
不使用 Pick<T, K> ,实现 TS 内置的 Pick<T, K> 的功能。 从类型 T 中选出符合 K 的属性,构造一个新的类型。
例如
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
}
答案:
type MyPick<T, K extends keyof T> =
{ [key in keyof T as key extends K ? key : never] : T[key] }
键名重映射(Key Remapping) 在 TypeScript 的映射类型里,这个 as 其实就是一个“改名器”或者“过滤器”。 你可以把 [key in keyof T as ...] 想象成一条工厂流水线: key in keyof T:工人把 T 这个对象里的所有属性(比如 name, age, gender)一个一个拿出来,挨个放在传送带上。 as ...:传送带中间加了一个“检查站”。工人会拿着这个属性去 as 后面的条件里比对,决定这个属性是“保留原名”、“改个新名字”,还是“直接扔掉”。
Includes
在类型系统里实现 JavaScript 的 Array.includes 方法,这个类型接受两个参数,返回的类型要么是 true 要么是 false。
例如:
type isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`
答案:
// 这道显然不是简单题,我不敢想象地狱难度会是什么样子的。。。
type Includes<T extends readonly any[], U> = { [P in T[number]]: true }[U] extends true ? true : false;
Push
在类型系统里实现通用的 Array.push 。
例如:
type Result = Push<[1, 2], '3'> // [1, 2, '3']
答案:
// 这道就比较简单了
type Push<T extends any[], U> = [...T, U]
Unshift
实现类型版本的 Array.unshift。
例如:
type Result = Unshift<[1, 2], 0> // [0, 1, 2]
答案:
// 这道和push也是一样的,就是调换了一下位置
type Unshift<T extends any[], U> = [U,...T]
Parameters
实现内置的 Parameters 类型,而不是直接使用它,可参考TypeScript官方文档。
例如:
const foo = (arg1: string, arg2: number): void => {}
type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]
答案:
// 使用infer获取到函数的参数的类型,并且把它赋给U
type MyParameters<T extends (...args: any[]) => any> = T extends (...args :infer U)=>any ? U : never