Utilisation du symbole comme type de clé d'objet dans TypeScript

20

J'essaie de définir un objet avec un symbole comme type de clé depuis MDN dit:

Une valeur de symbole peut être utilisée comme identifiant pour les propriétés des objets [...]

Mais en l'utilisant comme type pour la propriété clé:

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

entraîne l'erreur suivante:

TS1023: Un type de paramètre de signature d'index doit être «chaîne» ou «nombre».

même il peut être utilisé comme type d'index. J'utilise la dernière version dactylographiée ( v3.7.2), des questions connexes que j'ai trouvées:

J'ai également jeté un coup d'œil aux documents sur les symboles dactylographiés, mais ils montrent uniquement comment ils sont utilisés comme valeur, pas comme type.

Exemple:

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

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

Problème sur Microsoft / TypeScript

Ouvrir la demande de fonctionnalité

Simon
la source
Je pense que TypeScript ne prend en charge que des symboles spécifiques dans ses déclarations de type d'objet. Voulez - vous vraiment tout symbol ? Peut-être montrez-vous un exemple de la façon dont vous voulez utiliser votre type obj- je doute que toutes les propriétés à clé symbolique soient strings.
Bergi
@Bergi J'ai ajouté un exemple, j'ai peut-être supervisé quelque chose mais je ne peux pas trouver un moyen d'amener ts à accepter un symbole (sans utiliser anyce qui est une mauvaise pratique).
Simon
Je ne sais pas si Map<Symbol,String>j'ai raison, mais avez-vous essayé d'utiliser comme nous avons la carte, si cela pouvait servir l'objectif de ce que vous essayez de réaliser
pavan kumar
Même problème pour moi, je suppose que la partie ennuyeuse est la fausse publicité de la façon dont "TS est un surensemble de JS" - enfin, pas exactement. ceci en est un parfait exemple.
Patrick

Réponses:

3

Malheureusement, cela n'est pas possible pour le moment en TypeScript. Si vous devez interagir avec certaines API qui attendent cela ou veulent vraiment utiliser des symboles comme clés, vous pouvez faire cette version maladroite:

// 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
la source