TypeScript对象类型别名中属性引用同类型内其他属性的实现
问题描述
我定义了如下对象类型别名:
type PropsType = { options: string[]; display: object; }
如何重新定义display属性,使其以options的元素作为键?如何在同一类型定义中让一个属性引用另一个属性?
补充说明
我正在将现有React组件转换为TypeScript,该组件是一个自定义选择框(下拉菜单)。通常它会直接向用户展示options数组,但当options内容较为“晦涩”时,可以使用display选项。display对象以options中的每个元素作为键,显示字符串作为值。
示例:
<ChoiceBox options={["12345abcDEF", "3jijskjfkdjs", "kpofkjspklkds"]} display={{ "12345abcDEF": "Fish", "3jijskjfkdjs": "Frog", "kpofkjspklkds": "Pie" }} />
组件内部渲染逻辑:
<div>{display ? display[option] : option}</div>
解决方案
要实现让display的键与options的元素类型绑定,你需要用泛型来定义类型别名,这样就能在同一类型中让一个属性引用另一个的类型:
type PropsType<T extends string> = { options: T[]; display?: Record<T, string>; }
细节解释
- 泛型
T限定为字符串类型,用来指代options里每个元素的具体类型。 options: T[]把数组元素的类型固定为T,确保后续display的键能和它精准对应。display?: Record<T, string>里的?表示这个属性是可选的(毕竟组件支持不传入display直接展示原选项),Record<T, string>是TypeScript内置工具类型,专门用来定义“键为T类型、值为字符串类型”的对象,完美匹配你需要的display结构。
使用示例
当你使用组件时,TypeScript会自动推导泛型T的类型,或者你也可以显式指定:
// 自动推导T为"12345abcDEF" | "3jijskjfkdjs" | "kpofkjspklkds" <ChoiceBox options={["12345abcDEF", "3jijskjfkdjs", "kpofkjspklkds"]} display={{ "12345abcDEF": "Fish", "3jijskjfkdjs": "Frog", "kpofkjspklkds": "Pie" }} /> // 显式指定泛型类型 <ChoiceBox<"a" | "b"> options={["a", "b"]} display={{a: "选项A", b: "选项B"}} />
这样定义后,如果你传入的display键不在options的元素中,或者值不是字符串,TypeScript会直接抛出类型错误,完全贴合你的业务逻辑。
内容的提问来源于stack exchange,提问作者Julian Brooks
相关产品推荐
相关产品推荐

