如何用TypeScript泛型实现参数类型的相互依赖?
解决方案
不用提前提取类型,同时让第二个对象参数的键严格受第一个数组参数的字面量值约束,你可以这样写:
declare function test<T extends readonly string[]>(a: readonly [...T], b?: Record<T[number], string>): unknown; // 测试验证 test(['a', 'b'], { a: 'someValue', b: 'someOtherValue', c: 'thisShouldNotWork' // 此处会触发TypeScript错误,符合预期 });
为什么原写法无效?
你最初的代码里,TypeScript默认把['a', 'b']推断成了string[],而不是包含具体字面量的元组。这导致T[number]被解析为宽泛的string类型,Record<string, string>自然无法限制对象的键,所以c: 'thisShouldNotWork'不会报错。
方案原理
用readonly [...T]作为第一个参数的类型,会引导TypeScript将传入的数组推断为只读字面量元组。此时T[number]会被解析为数组元素的字面量联合类型(也就是'a' | 'b'),Record<T[number], string>就能正确约束第二个对象的键只能是数组中存在的字面量值。
另一种可选写法(需加as const)
如果不介意在调用时给数组加as const断言,也可以简化函数声明,同样能达到效果:
declare function test<T extends readonly string[]>(a: T, b?: Record<T[number], string>): unknown; test(['a', 'b'] as const, { a: 'someValue', b: 'someOtherValue', c: 'thisShouldNotWork' // 此处触发错误 });
as const会强制TypeScript把数组推断为只读字面量元组,同样避免了提前提取类型的步骤。
内容的提问来源于stack exchange,提问作者vinvin
相关产品推荐
相关产品推荐

