如何将泛型类型作为泛型参数传递?TypeScript类型编程疑问
TypeScript实现类型层面的高阶函数方案
你尝试在TypeScript中实现类型层面的高阶函数,但直接传递泛型类型别名时出现报错。以下是问题重现与解决方案:
问题重现
你可运行的代码示例:
type isArrStr<T extends readonly string[]> = T extends readonly["str"] ? true :false ; type _retAny<T> = any type wrapper<T> = any extends _retAny<isArrStr<infer I>> ? T extends I ? isArrStr<T> : never :never // 测试正常 let myVar:wrapper<readonly["str"]> // 返回true let myVar_1:wrapper<readonly["ll"]> // 返回false let myVar_2:wrapper<string> // 返回never
但尝试将泛型类型作为参数传递时,出现两个错误:
Type 'F' is not generic:TypeScript不允许直接将泛型类型别名作为泛型参数,需先约束F的类型为泛型构造器Generic type 'isArrStr' requires 1 type argument:泛型类型必须传入类型参数才能作为具体类型使用,直接传递泛型类型本身会报错
// 报错代码 type wrapper<F,T> = any extends _retAny<F<infer I>> ? T extends I ? F<T> : never :never // 错误:Type 'F' is not generic let myVar:wrapper<isArrStr,readonly["str"]> // 错误:Generic type 'isArrStr' requires 1 type argument
解决方案
要实现类型层面的高阶函数,需将泛型类型包装为泛型函数类型,并在高阶类型中约束F为接受单个类型参数的泛型函数,通过条件类型推断参数约束与返回类型,最终判断目标类型是否符合要求。
完整实现代码
// 原泛型类型:判断数组是否为readonly["str"] type isArrStr<T extends readonly string[]> = T extends readonly ["str"] ? true : false; // 高阶类型:接受泛型函数类型F与待检查类型T type wrapper<F extends <U>(arg: U) => any, T> = // 推断F的参数约束I和返回类型Result F extends <U extends infer I>(arg: U) => infer Result ? // 检查T是否符合F的参数约束 T extends I ? // 提取T对应的返回结果 Result extends (U extends T ? infer R : never) ? R : never : never : never; // 将原泛型类型包装为泛型函数类型 type IsArrStrFn = <U extends readonly string[]>(arg: U) => isArrStr<U>; // 测试验证 let myVar: wrapper<IsArrStrFn, readonly ["str"]>; // 类型为true let myVar_1: wrapper<IsArrStrFn, readonly ["ll"]>; // 类型为false let myVar_2: wrapper<IsArrStrFn, string>; // 类型为never
简洁写法(利用工具类型)
type isArrStr<T extends readonly string[]> = T extends readonly ["str"] ? true : false; type wrapper<F extends <U>(arg: U) => any, T> = T extends Parameters<F>[0] ? ReturnType<(F extends <U>() => infer R ? (() => R) : never)> extends (x: T) => infer Res ? Res : never : never; type IsArrStrFn = <U extends readonly string[]>(arg: U) => isArrStr<U>; // 测试结果一致 let myVar: wrapper<IsArrStrFn, readonly ["str"]>; // true let myVar_1: wrapper<IsArrStrFn, readonly ["ll"]>; // false let myVar_2: wrapper<IsArrStrFn, string>; // never
原理说明
- 泛型函数包装:将原泛型类型
isArrStr包装为泛型函数类型IsArrStrFn,使其成为可接受类型参数的"类型构造器" - 类型推断:在
wrapper中通过条件类型F extends <U extends infer I>(arg: U) => infer Result,推断出泛型函数的参数约束I和返回类型Result - 约束检查:判断目标类型
T是否符合参数约束I,符合则返回对应类型结果,否则返回never
内容的提问来源于stack exchange,提问作者issueWebpack
相关产品推荐
相关产品推荐

