TypeScript中的高阶泛型是指泛型参数本身也是泛型类型的情况。这种模式在函数式编程和复杂类型操作中非常有用。
基本概念
就像高阶函数接受函数作为参数一样,高阶泛型接受"类型构造器"作为参数。理想情况下,我们希望能够这样写::
// 基础的高阶泛型示例
type Higher<F<_>, T> = F<T>
// 使用示例
type ArrayOfString = Higher<Array, string> // Array<string>
type PromiseOfNumber = Higher<Promise, number> // Promise<number>
但如果你尝试一下,就会发现,这种语法在 TypeScript 还不支持。下面我们讨论一个替代方案。
基于类型映射表方案实现高阶泛型
通过预定义的类型映射表来实现高阶泛型效果:
// type Higher<F<_>, T> = F<T>
type Higher<Name extends keyof TypeMap<any>, T> = TypeMap<T>[Name]
// declare module "@/utils/type" {
// 可以在其他地方进行扩展
interface TypeMap<T> {
// 提前注册好类型,或者通过 ts 接口合并的特性在外部扩展
f1: Array<T>,
f2: Map<string, T>,
f3: Set<T>,
}
// }
// 使用
// Higher<Array<_>, number>
let h1: Higher<'f1', number> // Array<number>
// Higher<Map<string, _>, number>
let h2: Higher<'f2', number> // Map<string, number>
// Higher<Set<_>, number>
let h3: Higher<'f3', number> // Set<number>
尽管 TypeScript 尚未直接支持高阶泛型语法,但通过约束接口 和类型映射表 可模拟其核心功能。 在编写类库时,这种方案非常有用,给使用者提供很高的扩展性的同时还能保证类型安全和提示。
我前段时间编写了一个 FormTable 库,正是利用了这种特性实现超强的类型提示和扩展能力。