ключевое слово nameof в Typcript

Как я уже видел, не существует встроенного nameof -keyword , подобного С#, в котором встроен в TypeScript. Однако по тем же причинам, которые существуют в С#, я хочу иметь возможность ссылаться на имена свойств безопасным способом.

Это особенно полезно в TypeScript при использовании плагинов jQuery (Bootstrap-Tagsinput) или других библиотек, в которых необходимо настроить имя свойства.

Это может выглядеть так:

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

Назначение name также должно измениться, когда Console.log подвергся рефакторингу и переименовану.

Каков наиболее близкий способ использования такой функции в TypeScript на данный момент?

Ответ 1

Как вы уже сказали, в TypeScript нет встроенной функциональности начиная с версии 2.8. Однако есть способы получить тот же результат:

Вариант 1. Использование библиотеки

ts-nameof - это библиотека, которая обеспечивает ту же функциональность, что и С#. С этим вы можете сделать:

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

ts-simple-nameof предлагает альтернативу. Он в основном анализирует строковую лямбду, чтобы выяснить имя свойства:

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

Вариант 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 | symbol (ref). Если вы все еще хотите разрешать только строки, используйте эту реализацию:

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

Ответ 2

Я думаю, что нам часто нужно больше: получать имена свойств класса во время выполнения с проверкой во время компиляции. Это действительно полезная функция:

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