构建类型化SDK:TypeScript泛型约束函数参数且不捕获参数类型
如何让TypeScript函数的返回类型约束所有参数为该类型的子类型?
我正在构建一个类型化SDK,希望通过函数的返回类型来约束所有传入的参数,要求每个参数都符合返回类型,且参数之间的类型互不干扰。但当前实现遇到了问题:
function select<I extends R,R>(...items: I[]): R { return items[0]; } const r: string | number = select('s', 1); // 报错:Argument of type 'number' is not assignable to parameter of type 'string'.(2345)
当前表现:
- ✅ TypeScript能正确推断
R为string | number - ✅ 第一个参数可以接受
string | number类型 - ❌ 第二个参数只能接受
string类型(因为I被推断为第一个参数的类型string)
解决方案
不需要额外的泛型参数I,直接将参数列表定义为Array<R>,这样每个参数都会被约束为R的子类型,且参数之间的具体类型互不影响:
function select<R>(...items: R[]): R { return items[0]; } // 调用示例:无报错,参数类型互不干扰 const r: string | number = select('s', 1); const r2: string = select('a', 'b'); const r3: number | boolean = select(5, true);
如果需要强制至少传入一个参数(避免空参数调用),可以调整函数签名:
function select<R>(first: R, ...rest: R[]): R { return first; } select(); // 报错:Expected at least 1 arguments, but got 0.(2554)
原理说明
去掉多余的I泛型后,TypeScript会根据返回类型R(由调用时的变量类型或显式指定的泛型决定)直接约束所有参数必须属于R类型,每个参数只需满足自身是R的子类型即可,不再受其他参数的类型推断影响。
内容的提问来源于stack exchange,提问作者jfs
相关产品推荐
相关产品推荐

