TypeScript泛型:如何从第二个参数推导类型供第一个参数使用
该需求可以实现,核心解决方案是使用TypeScript函数重载适配两种调用场景。
问题原因说明
TypeScript的泛型参数推导是按参数从左到右的顺序执行的,你最初的写法里第一个参数listener的入参类型依赖泛型U,但U的实际类型需要第二个参数selector的返回值才能确定,左到右的推导顺序下TS没法先拿到右边selector的类型给左边用,所以会推导为unknown。
实现方案
通过函数重载分别定义「不传selector」和「传selector」两种调用签名,即可同时满足selector可选、参数顺序不变、类型自动推导三个要求:
export type Subscribe<T extends object> = { // 重载1:不传selector,默认返回完整state (listener: (slice: T) => void): void // 重载2:传selector,从selector返回值自动推导U类型 <U>(listener: (slice: U) => void, selector: (state: T) => U): void } // 测试验证 const subscribe = {} as Subscribe<{ value: number }> // 不传selector:入参自动推导为{ value: number } subscribe((state) => console.log(state.value)) // 传selector:value自动推导为number,无类型报错 subscribe( (value) => value * 2, (state) => state.value )
如果特殊场景下推导不符合预期,也可以在调用时手动指定泛型兜底,写法为subscribe<number>((value) => value * 2, (state) => state.value),上述重载方案已经可以覆盖绝大多数常规使用场景,不需要手动指定泛型。
内容的提问来源于stack exchange,提问作者user2541867
相关产品推荐
相关产品推荐

