如何让TypeScript泛型接口自动推断对象属性关联类型?
如何让TypeScript自动推断泛型接口的类型,无需显式指定T?
现有泛型接口I<T extends string | number>,要求保证属性val的类型与函数fn的返回类型完全一致,且类型只能是string或number。当前实现必须显式指定泛型参数T,想实现无需手动设置T,让TypeScript自动推断该类型,同时达到以下示例中的类型校验效果:
interface I<T extends string | number> { val: T; fn: () => T; } // 期望通过的代码 const x1: I = { val: "hello", fn: () => "world", }; const x2: I = { val: 3, fn: () => 4, }; // 期望被拒绝的代码 const x3: I = { val: "hello", fn: () => 4, }; const x4: I = { val: 3, fn: () => "world", };
解决方案
直接使用泛型接口I而不指定T是不合法的,TypeScript无法直接从赋值对象推断接口的泛型参数,但可以通过以下两种方式实现自动推断:
1. 用泛型函数辅助创建对象
通过定义一个泛型函数,让TypeScript从传入的对象参数自动推断T的类型,同时约束对象符合I<T>的结构:
interface I<T extends string | number> { val: T; fn: () => T; } function createValidI<T extends string | number>(obj: I<T>): I<T> { return obj; } // 正常通过,自动推断T为string const x1 = createValidI({ val: "hello", fn: () => "world", }); // 正常通过,自动推断T为number const x2 = createValidI({ val: 3, fn: () => 4, }); // 报错(符合预期):val是string,但fn返回number,类型不匹配 const x3 = createValidI({ val: "hello", fn: () => 4, }); // 报错(符合预期):val是number,但fn返回string,类型不匹配 const x4 = createValidI({ val: 3, fn: () => "world", });
2. 使用TypeScript 4.9+的satisfies关键字
如果你的项目使用TS 4.9及以上版本,可以用satisfies关键字直接约束对象结构,同时保留自动推断的类型:
interface I<T extends string | number> { val: T; fn: () => T; } // 定义所有合法的I类型联合 type ValidI = I<string> | I<number>; // 正常通过,自动推断类型为I<string> const x1 = { val: "hello", fn: () => "world", } satisfies ValidI; // 正常通过,自动推断类型为I<number> const x2 = { val: 3, fn: () => 4, } satisfies ValidI; // 报错(符合预期):对象不符合ValidI的约束 const x3 = { val: "hello", fn: () => 4, } satisfies ValidI; // 报错(符合预期):对象不符合ValidI的约束 const x4 = { val: 3, fn: () => "world", } satisfies ValidI;
原理说明
泛型接口本身必须显式指定类型参数,而上述两种方法都是通过外部上下文(函数参数或satisfies约束)让TypeScript自动推导T的类型,同时确保val和fn的返回类型一致,且仅限string或number。
内容的提问来源于stack exchange,提问作者user13203487
相关产品推荐
相关产品推荐

