为什么需要泛型
泛型让函数/类型在不丢失类型信息的前提下复用。没有泛型时只能退回 any,连带丢掉所有类型检查。
function identity<T>(value: T): T {
return value
}
const a = identity<string>('hello') // a: string
const b = identity(42) // b: number(自动推断)
泛型约束
用 extends 限制入参必须包含某些形状:
function pluck<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key]
}
pluck({ name: 'Cyrene', age: 18 }, 'name') // string
常用 Utility Types
| 类型 | 作用 |
|---|---|
Partial<T> |
所有属性变可选 |
Required<T> |
所有属性变必填 |
Pick<T, K> |
只取部分属性 |
Omit<T, K> |
排除部分属性 |
Record<K, V> |
构造键值映射类型 |
type User = { id: number; name: string; email: string }
type UserPreview = Pick<User, 'id' | 'name'> // { id; name }
条件类型与 infer
条件类型像类型的三元表达式,infer 可“提取”内部类型:
type ElementType<T> = T extends (infer U)[] ? U : T
type A = ElementType<number[]> // number
type B = ElementType<string> // string
ReturnType 就是基于此实现:
type R = ReturnType<() => Date> // Date
实战:安全取值
function get<T, K extends keyof T>(obj: T, key: K): T[K] | undefined {
return obj[key]
}
类型体操不是为了炫技,而是把运行时会崩的错提前到编译期。克制使用,读懂胜过写炫。