前言
最近想复习下 TS,所以想着练习一下 TS 类型体操,先实现了几个,后续可能还会继续更新!感兴趣的朋友也可以去 github 地址 试试。
实现 Pick
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
}
// T => Todo, keyof T 返回的是联合类型; K extend keyof T
// P in K // 遍历 K 联合类型,P 为联合类型中的 item, T[P] 为 Todo[P]
type MyPick<T, K extends keyof T> = {
[P in K]: T[P]
}
实现 ReadyOnly
interface Todo {
title: string
description: string
}
const todo: MyReadonly<Todo> = {
title: "Hey",
description: "foobar"
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
type MyReadonly<T> = {
readonly [K in keyof T]: T[K]
}
实现 元组转换为对象
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
// typeof tuple = readonly ['tesla', 'model 3', 'model X', 'model Y']
// T[number] 得到的是一个联合类型的
// T[number] === 'tesla' | 'model 3' | 'model X' | 'model Y'
type TupleToObject<T extends readonly any[]> = {
[K in T[number]]: K
}
实现获取 第一个元素
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]
type head1 = First<arr1> // expected to be 'a'
type head2 = First<arr2> // expected to be 3
type head3 = First<[]> // expected to be 3
type First<T extends any[]> = T extends [] ? never : T[0]; // 如果是空数组返回 never
// type First<T extends any[]> = T['length'] extends 0 ? never : T[0]; // 如果是空数组返回 never
实现 获取元组长度
type tesla = ['tesla', 'model 3', 'model X', 'model Y']
type spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']
type teslaLength = Length<tesla> // expected 4
type spaceXLength = Length<spaceX> // expected 5
// ts 类型也可以通过 length 属性直接获取到数组长度
type Length<T extends readonly any[]> = T['length'];
实现 Exclude
type Result = MyExclude<'a' | 'b' | 'c', 'a'> // 'b' | 'c'
// MyExclude 的比较方式, T 是联合类型,所以会对联合类型的每一个属性都比较一次( 我是这样理解的 😅 )
// 1. 'a' extends 'a' ? never : 'a';
// 2. 'b' extends 'a' ? never : 'b';
// 3. 'c' extends 'a' ? never : 'c';
type MyExclude<T, U> = T extends U ? never : T;