TypeScript中如何定义类型安全的函数链(上一函数输出作为下一函数输入)?泛型实现问题求助
TypeScript中如何定义类型安全的函数链(上一函数输出作为下一函数输入)?泛型实现问题求助
嗨,这个需求其实挺典型的——要让函数链里每一步的输入严格对应前一步的输出,你的思路方向是对的,只是在泛型递归的时候没给REST加上明确的类型约束,导致TypeScript没法跟踪它的类型了。
你原来的ChainLink定义里,REST只是被infer出来,但没有限定它必须是Mutator[]类型,所以递归到下一层的时候,TypeScript就不知道REST里的元素都是Mutator了,自然会出现类型丢失的问题。
我们只需要在infer REST的时候加上extends Mutator[]的约束,让TypeScript始终记得REST是Mutator数组就行,修改后的类型定义如下:
type Mutator<IN = any, OUT = any> = (obj: IN) => OUT; // 给REST加上extends Mutator[]的约束,确保递归时类型不丢失 type ChainLink<IN, A extends Mutator[] = [Mutator<IN>, ...Mutator[]]> = A extends [infer FIRST extends Mutator<IN, infer OUT>, ...infer REST extends Mutator[]] ? [FIRST, ...ChainLink<OUT, REST>] : []; // 测试用例 const stringToBoolean: Mutator<string, boolean> = (a) => true; const stringToString: Mutator<string, string> = (a) => "test"; const booleanToNumber: Mutator<boolean, number> = (b) => b ? 1 : 0; // 正确的链:string -> string -> boolean -> number,类型检查通过 const validChain: ChainLink<string> = [stringToString, stringToBoolean, booleanToNumber]; // 错误示例:如果把接收boolean的函数放在最前面,TypeScript会直接报错 // const invalidChain: ChainLink<string> = [booleanToNumber, stringToString]; // 类型不匹配,触发报错
关键修改点说明:
- 在
A extends [infer FIRST extends Mutator<IN, infer OUT>, ...infer REST extends Mutator[]]这一行,我们给两个推断值都加了明确约束:FIRST extends Mutator<IN, infer OUT>:确保第一个元素是接收IN类型并返回OUT类型的Mutator,同时提取出它的输出类型OUT作为下一层的输入...infer REST extends Mutator[]:明确REST是Mutator数组,这样递归到下一层时,TypeScript能继续跟踪每一步的输入输出类型关联
这样修改后,你的测试用例[stringToString, stringToBoolean]就能正常通过类型检查,而且如果函数链的顺序不对(比如把接收非初始类型的函数放在前面),TypeScript会立刻抛出类型错误,完美实现类型安全的函数链。
备注:内容来源于stack exchange,提问作者Programming Guy
相关产品推荐
相关产品推荐

