TypeScript如何基于数组对象的name值约束opts类型?
解决方案:使用联合类型数组实现元素级精准匹配
要让数组中每个元素的name和opts严格对应,你需要把Baz的所有合法实例组成联合类型,再将数组定义为该联合类型的数组,而非泛型数组或带默认泛型的类型。
完整实现代码
export type Option1 = { one: string; }; export type Option2 = { two: string; }; export type Name = 'first' | 'second'; export type Options<TName extends Name> = TName extends 'first' ? Option1 : TName extends 'second' ? Option2 : never; // 生成所有合法Baz实例的联合类型 type BazUnion = { [K in Name]: { name: K, opts: Options<K> } }[Name]; type MyObj = { foo: boolean, bar: string, baz: BazUnion[] };
原理说明
{ [K in Name]: { name: K, opts: Options<K> } }是映射类型,会遍历Name的每个成员生成对应结构:- 当
K='first'时,生成{ name: 'first', opts: Option1 } - 当
K='second'时,生成{ name: 'second', opts: Option2 }
- 当
- 最后用
[Name]索引该映射类型,提取所有值组成联合类型{name: 'first', opts: Option1} | {name: 'second', opts: Option2}。
效果验证
TypeScript会自动检查数组中每个元素的类型匹配:
// 合法:每个元素的name和opts对应正确 const validObj: MyObj = { foo: true, bar: 'test', baz: [ { name: 'first', opts: { one: 'hello' } }, { name: 'second', opts: { two: 'world' } } ] }; // 非法:name为'first'但opts用了Option2的结构,TypeScript会报错 const invalidObj: MyObj = { foo: true, bar: 'test', baz: [ { name: 'first', opts: { two: 'error' } } // 类型不匹配,报错 ] };
这样既解决了泛型参数缺失的问题,又保证了每个数组元素的name和opts精准绑定。
内容的提问来源于stack exchange,提问作者plusheen
相关产品推荐
相关产品推荐

