外观
泛型和高级类型在面试里怎么讲?
泛型把类型当成参数,让输入和输出保持联系。高级类型是在已有类型上做运算:联合、交叉、条件、映射,以及 Partial、Pick 这些工具类型。它们都在编译期展开,运行时没有这些名字。
原理
ts
function first<T>(list: T[]): T | undefined {
return list[0]
}T 由调用时的实参推断。约束写成 <T extends { id: string }>,函数里才能读 id。默认类型参数用 =。
条件类型 T extends U ? X : Y 按兼容关系选择。infer 能在条件里抽出一部分,例如函数返回值。分配条件类型遇到联合时会逐个分配,这是 Exclude 的原理。
映射类型遍历键:{ [K in keyof T]: ... }。Partial<T> 把每个属性变成可选,Pick<T, K> 只留下若干键,Record<K, V> 声明字典。keyof 取出键的联合。
unknown 要收窄再用。never 表示不会出现的分支,用来检查联合是否被穷尽。
追问
和 any 的差别?
any 关掉检查。泛型在使用处仍是具体类型。拿不准外部数据时用 unknown,不要写成泛型的 T 却在内部当成任意字段去读。
条件类型什么时候会难读?
叠了两三层 infer 就该起一个名字,并配一个例子类型。面试写 ReturnType、Partial 的展开即可,不必背库里的全部定义。
易错点
- 泛型函数在实现里把
T换成某个具体类型返回,调用方的推断就说谎了。 - 以为
Partial会把嵌套对象也变成可选。它只作用在第一层。 - 运行时去读
keyof的结果。擦除之后这些类型都不在。