Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript中关键字的名称_Typescript_Types - Fatal编程技术网

Typescript中关键字的名称

Typescript中关键字的名称,typescript,types,Typescript,Types,正如我所看到的,TypeScript中没有内置本机的nameof-关键字。但是,出于C#中存在的相同原因,我希望能够以类型安全的方式引用属性名称 当使用jQuery插件()或其他需要配置属性名称的库时,这在TypeScript中特别有用 它可能看起来像: const name: string = nameof(Console.log); // 'name' is now equal to "log" 当Console.log被重构和重命名时,name的分配也应该改变 到目前为止,在TypeSc

正如我所看到的,TypeScript中没有内置本机的
nameof
-关键字。但是,出于C#中存在的相同原因,我希望能够以类型安全的方式引用属性名称

当使用jQuery插件()或其他需要配置属性名称的库时,这在TypeScript中特别有用

它可能看起来像:

const name: string = nameof(Console.log);
// 'name' is now equal to "log"
Console.log
被重构和重命名时,
name
的分配也应该改变


到目前为止,在TypeScript中使用此类功能的最接近的方法是什么?

正如您所说,从2.8版开始,TypeScript上没有内置功能。但是,有几种方法可以获得相同的结果:

选项1:使用库 是一个提供与C#完全相同的功能的库。有了它,您可以:

nameof(console); // => "console"
nameof(console.log); // => "log"
nameof<MyInterface>(); // => "MyInterface"
nameof<MyNamespace.MyInnerInterface>(); // => "MyInnerInterface"
它将返回传递的属性名,但当类型
T
上不存在属性名时,将生成编译时错误。像这样使用它:

interface Person {
    firstName: string;
    lastName: string;
}

const personName1 = nameof<Person>("firstName"); // => "firstName"
const personName2 = nameof<Person>("noName");    // => compile time error

我认为我们通常需要更多:通过编译时验证在运行时获取类属性名。这是一个非常有用的功能:

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);
}
现有实例的示例:

export interface I_$<T> {
    nameOf<V extends T[keyof T]>(f: (x: T) => V): valueOf<{ [K in keyof T]: T[K] extends V ? K : never }>;
}

export function _$<T>(obj: T) {
    return {
        nameOf: (f: (x: any) => any) => {
            return nameOf(f);
        }
    } as I_$<T>;
}

在编译时解析为“someProperty”

如果您只需要以字符串形式访问属性,您可以像这样安全地使用代理:

函数字段(){
返回新代理(
{},
{
获取:函数(目标、道具、接收器){
返回道具;
},
}
)作为{
[P in keyof T]:P;
};
};
接口资源行{
id:编号;
磁盘上已修改的\u:日期;
本地路径:字符串;
服务器路径:字符串;
}
常数f=字段();
//在本例中,我展示了如何将字段名类型安全地嵌入到SQL字符串中:
常量sql=`
如果资源不存在,则创建表(
${f.id}整数主键自动递增不为空,
${f.modified_on_disk}DATETIME不为空,
${f.local_path}VARCHAR(2048)非空唯一,
${f.server_path}VARCHAR(2048)非空唯一
);
`;

下面是添加到列表中的另一项工作——我非常喜欢编译时的转换名称。节省了其他解决方案提供的解析表达式等的可能开销。这里发生了什么:
export function nameOf(f:(x:T)=>V):valueOf
const nameof = <T>(name: Extract<keyof T, string>): string => name;
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)) {
   // ...                               
}
export interface I_$<T> {
    nameOf<V extends T[keyof T]>(f: (x: T) => V): valueOf<{ [K in keyof T]: T[K] extends V ? K : never }>;
}

export function _$<T>(obj: T) {
    return {
        nameOf: (f: (x: any) => any) => {
            return nameOf(f);
        }
    } as I_$<T>;
}
let obj: SomeClass = ...;
_$(obj).nameOf(x => x.someProperty)