TypeScript寻找C# nameof替代方案,实现变量值等于自身变量名
需求说明
需要在TypeScript中创建值与自身变量名相等的只读字符串,实现C#中nameof函数的效果:C#中可以直接用public static readonly string Admin = nameof(Admin);得到值为"Admin"的变量,但TypeScript中原生不支持在变量初始化时调用自身,直接照搬写法会触发初始化前调用的错误。
C#可运行参考代码:
public static readonly string Admin = nameof(Admin); // Admin最终取值为字符串"Admin"
原错误实现说明
最初尝试的TS代码如下:
export class Resources { static nameof(variable: Object): string{ const keys = Object.keys(variable); return keys[0]; } static readonly Admin = Resources.nameof(Resources.Admin); }
运行时抛出错误:Property 'Admin' is used before its initialization.,错误原因是静态属性赋值阶段Resources.Admin还未完成初始化,无法作为参数传入函数。
可行解决方案
方案1:批量生成常量(推荐,适合多属性场景)
如果需要生成大量这类常量,可以通过泛型工具函数批量创建,同时保证类型安全:
// 定义类型约束,保证属性名和属性值严格一致 type ValueMatchKey<T extends string> = { readonly [K in T]: K }; function createConstants<T extends string>(keys: readonly T[]): ValueMatchKey<T> { return keys.reduce((result, key) => { result[key] = key; return result; }, {} as ValueMatchKey<T>); } // 用法:把所有需要的属性名传入数组即可 export const Resources = createConstants(['Admin', 'User', 'Editor', 'Guest'] as const);
实现效果:
Resources.Admin的值固定为"Admin",所有属性默认只读,无法修改- TypeScript可以自动推导每个属性的字面量类型,输入不存在的属性名会直接报类型错误
- 新增属性只需要在传入的数组中加项即可,维护成本低
方案2:Getter实现(适合少量属性场景)
如果仅需要少量属性,可以直接用类的静态Getter模拟只读属性:
export class Resources { static get Admin(): 'Admin' { return 'Admin'; } static get User(): 'User' { return 'User'; } static get Guest(): 'Guest' { return 'Guest'; } }
该写法没有初始化顺序问题,访问属性时返回对应名称的字符串,同样满足只读要求。
方案3:编译期替换(最接近C# nameof体验)
如果希望完全复用C#的nameof写法,可以通过自定义TypeScript编译插件,在编译阶段直接把nameof(变量)的调用替换为对应的字符串字面量,不需要运行时代码,也不会触发初始化顺序错误。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

