TypeScript:从嵌套对象值生成新类型时无键报错,如何解决?
问题原因与解决方法
问题出在哪?
AllValuesOf类型逻辑错误:你写的AllValuesOf<T>尝试取T[keyof T],但Events是数组类型,keyof T包含了数组的所有键(比如length、push这些数组方法/属性),所以T[keyof T]拿到的不只是数组里的对象元素,还混进了数组本身的属性类型,完全偏离了你的需求。- 联合类型存在无
name属性的成员:就算你拿到了数组元素的联合类型({name: 'foo'} | {name: 'bar'} | {value: 'baz'}),直接访问['name']也会报错,因为联合类型里的{value: 'baz'}没有name属性,TypeScript 不允许访问联合类型中不存在的属性。
正确实现方式
要达到预期效果,需要分两步:
- 提取数组的元素类型(用
T[number],数组的数字索引对应的就是元素); - 过滤出带有
name属性的元素类型,再提取name的值类型。
修改后的代码:
const events = [ { name: 'foo' }, { name: 'bar' }, { value: 'baz' } ] as const; type Events = typeof events; // 提取数组元素类型,再过滤出有name属性的类型,最后取name的值 type Name = Extract<Events[number], { name: unknown }>['name']; // 结果:"foo" | "bar"
或者用条件类型实现:
type NameFromArray<T extends readonly any[]> = T[number] extends { name: infer N } ? N : never; type Name = NameFromArray<Events>; // "foo" | "bar"
两种方式都能正确得到你想要的 'foo' | 'bar' 类型。
内容的提问来源于stack exchange,提问作者Vikas
相关产品推荐
相关产品推荐

