Usando símbolo como tipo de chave de objeto no TypeScript

20

Estou tentando definir um objeto com um símbolo como tipo de chave, já que o MDN diz:

Um valor de símbolo pode ser usado como um identificador para propriedades do objeto [...]

Mas usando-o como tipo para a propriedade-chave:

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

resulta no seguinte erro:

TS1023: Um tipo de parâmetro de assinatura de índice deve ser 'string' ou 'number'.

mesmo ele pode ser usado como tipo de índice. Estou usando a última versão datilografada ( v3.7.2), perguntas relacionadas que encontrei:

Também demos uma olhada nos documentos de símbolos datilografados, mas eles mostram apenas como é usado como valor, não como tipo.

Exemplo:

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

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

Problema no Microsoft / TypeScript

Solicitação de recurso aberto

Simon
fonte
Eu acho que o TypeScript suporta apenas símbolos específicos em suas declarações de tipo de objeto. Você realmente quer alguma symbol ? Talvez mostre um exemplo de como você deseja usar o seu type obj- duvido que todas as propriedades com chave de símbolo sejam strings.
Bergi 30/11/19
@ Bergi Adicionei um exemplo, talvez tenha supervisionado alguma coisa, mas não consigo encontrar uma maneira de fazer com que os ts aceitem um símbolo (sem usar o anyque é uma má prática).
Simon
não tenho certeza se estou certo, mas se você tentar usar Map<Symbol,String>como temos Mapa, se isso iria servir o propósito de que você está tentando alcançar
Kumar Pavan
O mesmo problema para mim, acho que a parte irritante é a publicidade falsa de como "TS é um superconjunto de JS" - bem, não exatamente. este é um exemplo perfeito disso.
Patrick

Respostas:

3

Infelizmente, isso não é possível no momento no TypeScript. Se você precisar interoperar com algumas APIs que esperam isso ou realmente desejam usar símbolos como chaves, é possível fazer esta versão complicada:

// 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
Dmitriy
fonte