Использование символа в качестве типа ключа объекта в 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- я сомневаюсь, что все свойства stringс символьным ключом будут s.
Берги
@ Bergi Я добавил пример, может быть, я что-то наблюдал, но я не могу найти способ заставить t принять символ (без использования, 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
Дмитрий
источник