正如我所看到的,TypeScript中没有内置nameof
- 关键字like C# has。但是,出于与C#相同的原因,我希望能够以类型安全的方式引用属性名称。
当使用jQuery插件(Bootstrap-Tagsinput)或其他需要配置属性名称的库时,这在TypeScript中特别有用。
它可能看起来像:
const name: string = nameof(Console.log);
// 'name' is now equal to "log"
当name
被重构和重命名时,Console.log
的分配也会发生变化。
目前在TypeScript中使用此类功能的最近方法是什么?
答案 0 :(得分:21)
正如您已经说过的,从版本2.8开始,TypeScript上没有内置功能。但是,有一些方法可以得到相同的结果:
ts-nameof是一个提供C#确切功能的库。有了这个,你可以这样做:
nameof(console); // => "console"
nameof(console.log); // => "log"
nameof<MyInterface>(); // => "MyInterface"
nameof<MyNamespace.MyInnerInterface>(); // => "MyInnerInterface"
您可以轻松定义自己添加类型检查的nameof
,但它不会自动重构,因为您仍然需要输入字符串文字:
const nameof = <T>(name: keyof T) => name;
它将返回传递的属性名称,但是当类型T
上的属性名称不存在时,将生成编译时错误。像这样使用它:
interface Person {
firstName: string;
lastName: string;
}
const personName1 = nameof<Person>("firstName"); // => "firstName"
const personName2 = nameof<Person>("noName"); // => compile time error
Credits and more information about this
类型keyof T
现在不仅解析为字符串,还解析为string | number | symbol
(ref)。如果您仍想要仅解析字符串,请改用此实现:
const nameof = <T>(name: Extract<keyof T, string>): string => name;
答案 1 :(得分:6)
我认为我们经常需要更多:在运行时通过编译时验证来获取类属性名称。这是一个非常有用的功能:
export type valueOf<T> = T[keyof T];
export function nameOf<T, V extends T[keyof T]>(f: (x: T) => V): valueOf<{ [K in keyof T]: T[K] extends V ? K : never }>;
export function nameOf(f: (x: any) => any): keyof any {
var p = new Proxy({}, {
get: (target, key) => key
})
return f(p);
}
用法示例(无字符串!):
if (update.key !== nameOf((_: SomeClass) => _.someProperty)) {
// ...
}
答案 2 :(得分:1)
如果只需要以字符串形式访问属性,则可以安全地使用Proxy,如下所示:
function fields<T>() {
return new Proxy(
{},
{
get: function (_target, prop, _receiver) {
return prop;
},
}
) as {
[P in keyof T]: P;
};
};
interface ResourceRow {
id: number;
modified_on_disk: Date;
local_path: string;
server_path: string;
}
const f = fields<ResourceRow>();
// In this example I show how to embed field names type-safely to a SQL string:
const sql = `
CREATE TABLE IF NOT EXISTS resource (
${f.id} INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
${f.modified_on_disk} DATETIME NOT NULL,
${f.local_path} VARCHAR (2048) NOT NULL UNIQUE,
${f.server_path} VARCHAR (2048) NOT NULL UNIQUE
);
`;