typescript 打字稿中的关键字名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50470025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:25:52  来源:igfitidea点击:

nameof keyword in Typescript

typescripttypes

提问by Bruno Zell

As I have seen, there is no native nameof-keyword like C# hasbuilt into TypeScript . However, for the same reasons this exists in C#, I want to be able to refer to property names in a type safe manner.

正如我所看到的,没有提供原生nameof-keyword如C#已建成打字稿。但是,出于与 C# 中存在的相同原因,我希望能够以类型安全的方式引用属性名称。

This is especially useful in TypeScript when using jQuery plugins (Bootstrap-Tagsinput) or other libraries where the name of a property needs to be configured.

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

It could look like:

它可能看起来像:

const name: string = nameof(Console.log);
// 'name' is now equal to "log"

The assignment of nameshould change too when Console.loggot refactored and renamed.

nameConsole.log重构和重命名时,的分配也应该改变。

What is the closest possible way of using such a feature in TypeScript as of now?

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

回答by Bruno Zell

As you have already said, there is no built in functionality on TypeScript as of version 2.8. However, there are ways to get the same result:

正如您已经说过的,从 2.8 版开始,TypeScript 没有内置功能。但是,有一些方法可以获得相同的结果:

Option 1: Using a library

选项 1:使用库

ts-nameofis a library that provides the exact functionality as C# does. With this you can do:

ts-nameof是一个提供与 C# 完全相同的功能的库。有了这个,你可以:

nameof(console); // => "console"
nameof(console.log); // => "log"
nameof<MyInterface>(); // => "MyInterface"
nameof<MyNamespace.MyInnerInterface>(); // => "MyInnerInterface"

ts-simple-nameofoffers an alternative. It basically parses a stringified lambda to figure out the property name:

ts-simple-nameof提供了一个替代方案。它基本上解析一个字符串化的 lambda 来找出属性名称:

nameof<Comment>(c => c.user); // => "user"
nameof<Comment>(c => c.user.posts); // => "user.posts"

Option 2: Define a helper function

选项 2:定义辅助函数

You can easily define your own nameofthat adds the type checking, however it will not refactor automatically as you'll still need to type a string literal:

您可以轻松定义自己的nameof添加类型检查的方法,但是它不会自动重构,因为您仍然需要输入字符串文字:

const nameof = <T>(name: keyof T) => name;

It will return the passed property name but will generate a compile time error when the property name does not exist on type T. Use it like so:

它将返回传递的属性名称,但当属性名称不存在于 type 时会生成编译时错误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

积分和有关此的更多信息

Update on helper function with TypeScript 2.9+

使用 TypeScript 2.9+ 更新辅助函数

The type keyof Tnow not only resolves to a string, but to string | number | symbol(ref). If you still want to resolve strings only, use this implementation instead:

该类型keyof T现在不仅解析为字符串,而且解析为string | number | symbol( ref)。如果您仍然只想解析字符串,请改用此实现:

const nameof = <T>(name: Extract<keyof T, string>): string => name;

回答by SalientBrain

I think we often need more: to get class property names at runtime with compile-time validation. This is a really useful feature:

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

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);
}

Usage example (no strings!):

用法示例(无字符串!):

if (update.key !== nameOf((_: SomeClass) => _.someProperty)) {
   // ...                               
}

Example with existing instance:

现有实例的示例:

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>;
}

Usage:

用法:

let obj: SomeClass = ...;
_$(obj).nameOf(x => x.someProperty)

resolved to 'someProperty' at compile time

在编译时解析为 'someProperty'