web-dev-qa-db-ja.com

Typescriptのnameofキーワード

私が見たように、ネイティブのnameof- keyword C#が持っているような はTypeScriptに組み込まれていません。ただし、これがC#に存在するのと同じ理由で、タイプセーフな方法でプロパティ名を参照できるようにしたいと考えています。

これは、jQueryプラグイン( Bootstrap-Tagsinput )またはプロパティの名前を設定する必要がある他のライブラリを使用する場合、TypeScriptで特に役立ちます。

次のようになります。

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

nameの割り当ても、Console.logはリファクタリングされ、名前が変更されました。

TypeScriptでこのような機能を使用する最も近い可能な方法は何ですか?

25
Bruno Zell

既に述べたように、バージョン2.8の時点でTypeScriptには組み込みの機能はありません。ただし、同じ結果を得る方法があります。

オプション1:ライブラリを使用する

ts-nameof は、C#と同様の正確な機能を提供するライブラリです。これにより、次のことができます。

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

オプション2:ヘルパー関数を定義する

型チェックを追加する独自の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

これに関するクレジットと詳細

TypeScript 2.9+でのヘルパー関数の更新

タイプ keyof Tは、文字列だけでなく、string | number | symbolref )。それでも文字列のみを解決する場合は、代わりに次の実装を使用します。

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

実行時にクラスプロパティ名を取得し、コンパイル時の検証を行う必要がある場合が多いと思います。これは本当に便利な機能です。

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)) {
   // ...                               
}
3
SalientBrain