TypeScript如何实现自引用泛型函数,从入参对象属性值推断泛型类型
解决方案
你需要先定义一个工具类型提取所有夹具的返回值类型,再将夹具的入参类型和返回值集合关联,就可以实现你要的类型推导效果,完整代码如下:
type TestFixture<ReturnT, ExtraArgs = {}> = (args: ExtraArgs, use: (val: ReturnT) => void) => void // 工具类型:从夹具集合中提取每个夹具的返回值,组成依赖对象的类型 type FixtureReturnMap<T extends Record<string, TestFixture<any, any>>> = { [K in keyof T]: T[K] extends TestFixture<infer R, any> ? R : never } // 定义夹具组的工具函数 const defineFixtureGroup = <T extends Record<string, TestFixture<any, FixtureReturnMap<T>>>>(fixtures: T) => fixtures // 可选:如果你要保留createTestFixture封装,可以用高阶函数提前绑定返回值类型 const createTestFixture = <ReturnT>() => { return <ExtraArgs>(fn: TestFixture<ReturnT, ExtraArgs>) => fn } // 使用示例 type TestA = number type TestB = string const res = defineFixtureGroup({ testA: createTestFixture<TestA>()((d, use) => { // d.testB 自动推导为 string 类型 d.testB use(1) }), testB: createTestFixture<TestB>()((d, use) => { // d.testA 自动推导为 number 类型 d.testA use('abc') }), })
实现说明
- 你之前的代码核心问题是把夹具对象本身的类型直接作为了夹具函数的第一个入参类型,而实际你需要的入参是每个夹具返回值的集合,所以需要用
FixtureReturnMap工具类做一次类型映射,把每个夹具函数的返回值提取出来组成新的类型。 - 泛型约束中
T extends Record<string, TestFixture<any, FixtureReturnMap<T>>>的作用是让TS自动推导循环关联的类型,不需要你手动声明每个夹具的入参类型。 - 如果你不需要单独的
createTestFixture封装,直接在defineFixtureGroup里写夹具函数也能得到正确的类型推导。
内容的提问来源于stack exchange,提问作者jonathancardoso
相关产品推荐
相关产品推荐

