如何从TypeScript类型中获取属性名的字符串表示?
解决TypeScript从类型派生属性名常量的问题
你之前用Mapped Types定义的MyTypeProp只是编译时的类型,不是运行时可访问的变量——TypeScript的类型信息在编译后会被完全移除,所以没法直接用类型生成运行时的属性名对象。要实现o[MyTypeProp.name]这种安全访问,需要同时创建符合类型约束的运行时常量和对应的类型。
方法1:手动创建常量+类型约束(简单直接)
先定义包含所有属性名的常量对象,用as const锁定它的类型,同时通过TypeScript的类型检查确保它和MyType的属性完全匹配:
type MyType = { name: string, age: number, }; // 手动创建属性名常量,as const确保值不会被修改,类型会被推断为字面量类型 const MyTypeProp = { name: "name", age: "age" } as const; // 验证类型:MyTypeProp的键和值都是MyType的属性名 type MyTypePropType = typeof MyTypeProp;
现在你就可以安全地用它访问对象属性:
const o: MyType = { name: "John Doe", age: 42 }; console.log(o[MyTypeProp.name]); // 输出"John Doe"
测试场景中也可以摆脱魔法字符串:
expect(allDisabled(model, [MyTypeProp.name, MyTypeProp.age])).toBe(true);
方法2:用辅助函数自动约束一致性(避免手动维护出错)
如果MyType后续会修改,手动维护MyTypeProp容易遗漏属性。可以写一个辅助函数,强制要求常量对象必须包含MyType的所有属性:
// 辅助函数:约束传入的对象必须包含T的所有键,且值对应键名 function createPropKeys<T>() { return <U extends Record<keyof T, keyof T>>(obj: U) => obj; } // 创建MyType对应的属性名常量,若MyType新增属性,这里会直接报错 const MyTypeProp = createPropKeys<MyType>()({ name: "name", age: "age" });
这样只要MyType的属性有变动,TypeScript会立即提示你更新MyTypeProp,保证两者的一致性。
关键说明
TypeScript的类型系统是编译时专属的,不存在“从类型自动生成运行时变量”的能力——所有运行时能用的变量必须显式定义。但通过类型约束,可以让这些变量和你的类型严格绑定,彻底消除魔法字符串带来的维护风险。
内容的提问来源于stack exchange,提问作者Thomas Junk
相关产品推荐
相关产品推荐

