Utilizzo del simbolo come tipo di chiave oggetto in TypeScript


20

Sto cercando di definire un oggetto con un simbolo come tipo di chiave poiché MDN dice:

Un valore di simbolo può essere utilizzato come identificatore per le proprietà degli oggetti [...]

Ma usandolo come tipo per la proprietà-chiave:

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

provoca il seguente errore:

TS1023: Un tipo di parametro di firma indice deve essere 'stringa' o 'numero'.

anche può essere usato come tipo di indice. Sto usando l'ultima versione di dattiloscritto ( v3.7.2), domande correlate che ho trovato:

Ho anche dato un'occhiata ai documenti dei simboli dattiloscritti, ma mostrano solo come viene usato come valore, non come tipo.

Esempio:

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

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

Problema su Microsoft / TypeScript

Apri richiesta funzionalità


Penso che TypeScript supporti solo simboli specifici nelle sue dichiarazioni del tipo di oggetto. Vuoi davvero qualsiasi symbol ? Magari mostra un esempio di come vuoi usare il tuo type obj- Dubito che tutte le proprietà con chiave di simbolo saranno strings.
— Bergi,

@Bergi Ho aggiunto un esempio, forse ho supervisionato qualcosa ma non riesco a trovare un modo per indurre ts ad accettare un simbolo (senza usare anyquale è una cattiva pratica).
— Simon,


non sono sicuro di aver ragione, ma hai provato a usare Map<Symbol,String>come abbiamo Map, se questo avrebbe avuto lo scopo di quello che stai cercando di ottenere
— pavan kumar

Lo stesso problema per me, immagino che la parte fastidiosa sia la falsa pubblicità di come "TS è un superset di JS" - beh, non esattamente. questo è un esempio perfetto di ciò.
— Patrick

Risposte:


3

Purtroppo questo non è possibile al momento in TypeScript. Se devi interagire con alcune API che si aspettano questo o vogliono davvero usare i simboli come chiavi, puoi fare questa versione scomoda:

// 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.