Використання символу як типу об'єктного ключа в TypeScript


20

Я намагаюся визначити об'єкт із символом як тип ключа, оскільки MDN говорить:

Значення символу може бути використане як ідентифікатор властивостей об'єкта [...]

Але використовуючи його як тип для властивості ключа:

type obj = {
    [key: symbol | string]: string
}

призводить до наступної помилки:

TS1023: Тип параметра підпису індексу повинен бути або "рядок", або "число".

навіть він може використовуватися як індексний тип. Я використовую останню версію машинопису ( v3.7.2), пов'язані з нами питання:

Я також розглянув документи символів машинопису, але вони лише показують, як він використовується як значення, а не як тип.

Приклад:

const obj = {} as {
    [key: number | symbol]: string // Won't work
};

const sym = Symbol('My symbol');
obj[sym] = 'Hi';

Випуск у Microsoft / TypeScript

Відкрити запит на функцію


Я думаю, що TypeScript підтримує лише конкретні символи у своїх деклараціях типу об'єкта. Ви справді хочете будь-якого symbol ? Можливо, покажіть приклад того, як ви хочете використовувати свої type obj- я сумніваюся, що всі властивості, націлені символом, будуть strings.
Берги

@Bergi Я додав приклад, можливо, я щось наглядав, але не можу знайти спосіб прийняти тс, щоб прийняти символ (без використання anyшкідливої ​​практики).
Саймон


я не впевнений, чи маю рацію, але ти намагався використовувати, Map<Symbol,String>як у нас Карта, якщо це буде служити цілі того, чого ти намагаєшся досягти
pavan kumar

Це ж питання для мене, я думаю, що дратує частину помилкову рекламу того, як "TS - це суперсеть JS" - ну не точно. це прекрасний приклад тому.
Патрік

Відповіді:


3

На жаль, наразі це неможливо в TypeScript. Якщо вам доведеться взаємодіяти з деякими API, які очікують на це або дійсно хочуть використовувати символи як ключі, ви можете зробити цю незручну версію:

// Ensure we can not pass regular map to our custom functions
type SymbolMapTag = { readonly symbol: unique symbol }

type SymbolMap = SymbolMapTag & {
    [Key in string | number | symbol]: string;
}

function set_symbol<T extends SymbolMap, TSym extends symbol>
(target: T, sym: TSym, value: T[TSym]) {
    target[sym] = value;
}

function get_symbol<T extends SymbolMap, TSym extends symbol>
(target: T, sym: TSym): T[TSym] {
    return target[sym];
}

const symbol_map = {} as SymbolMap;

const sym = Symbol('My symbol');
set_symbol(symbol_map, sym, "hi");
get_symbol(symbol_map, sym); // string


type NonSymbolMap = {
    [Key in string | number]: string;
}

const non_symbol_map = {} as NonSymbolMap;
set_symbol(non_symbol_map, sym, "hi"); // error
get_symbol(non_symbol_map, sym); // error
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.