Usando el símbolo como tipo de clave de objeto en TypeScript

20

Estoy tratando de definir un objeto con un símbolo como tipo de clave ya que MDN dice:

Se puede usar un valor de símbolo como identificador para las propiedades [...] del objeto

Pero usándolo como tipo para la propiedad clave:

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

da como resultado el siguiente error:

TS1023: un tipo de parámetro de firma de índice debe ser 'string' o 'number'.

incluso se puede usar como tipo índice. Estoy usando la última versión mecanografiada ( v3.7.2), preguntas relacionadas que he encontrado:

También he echado un vistazo a los documentos de símbolos mecanografiados, pero solo muestran cómo se usa como valor, no como tipo.

Ejemplo:

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

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

Problema en Microsoft / TypeScript

Solicitud de función abierta

Simón
fuente
Creo que TypeScript solo admite símbolos específicos en sus declaraciones de tipo de objeto. ¿De verdad quieres alguno symbol ? Tal vez muestre un ejemplo de cómo desea usar su type obj- Dudo que todas las propiedades con clave de símbolo sean strings.
Bergi
@Bergi He agregado un ejemplo, tal vez he supervisado algo, pero no puedo encontrar una manera de hacer que ts acepte un símbolo (sin usar, lo anycual es una mala práctica).
Simon
No estoy seguro de si estoy en lo cierto, pero ¿trataste de usarlo Map<Symbol,String>como tenemos Map? Si eso serviría para lo que estás tratando de lograr
pavan kumar
El mismo problema para mí, supongo que la parte molesta es la publicidad falsa de cómo "TS es un superconjunto de JS", bueno, no exactamente. este es un ejemplo perfecto de eso.
Patrick

Respuestas:

3

Desafortunadamente, esto no es posible en este momento en TypeScript. Si tiene que interactuar con algunas API que esperan esto o realmente quieren usar símbolos como claves, puede hacer esta versión incómoda:

// 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
fuente