Verwenden des Symbols als Objektschlüsseltyp in TypeScript

20

Ich versuche, ein Objekt mit einem Symbol als Schlüsseltyp zu definieren, da MDN Folgendes sagt:

Ein Symbolwert kann als Kennung für Objekteigenschaften verwendet werden [...]

Verwenden Sie es jedoch als Typ für die Schlüsseleigenschaft:

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

führt zu folgendem Fehler:

TS1023: Ein Indexsignaturparametertyp muss entweder 'string' oder 'number' sein.

sogar es kann als Indextyp verwendet werden. Ich verwende die neueste Typoskript-Version ( v3.7.2). Verwandte Fragen, die ich gefunden habe:

Ich habe mir auch die Typoskript-Symboldokumente angesehen aber sie zeigen nur, wie sie als Wert und nicht als Typ verwendet werden.

Beispiel:

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

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

Problem mit Microsoft / TypeScript

Funktionsanforderung öffnen

Simon
quelle
Ich denke, TypeScript unterstützt nur bestimmte Symbole in seinen Objekttypdeklarationen. Wollen Sie wirklich jeder symbol ? Zeigen Sie vielleicht ein Beispiel dafür, wie Sie Ihre verwenden möchten type obj- ich bezweifle, dass alle Eigenschaften mit Symbolschlüssel strings sein werden.
Bergi
@Bergi Ich habe ein Beispiel hinzugefügt, vielleicht habe ich etwas beaufsichtigt, aber ich kann keinen Weg finden, ts dazu zu bringen, ein Symbol zu akzeptieren (ohne es zu verwenden, anywas eine schlechte Praxis ist).
Simon
Map<Symbol,String>
Ich bin
Das gleiche Problem für mich, ich denke, der nervige Teil ist die falsche Werbung dafür, wie "TS eine Obermenge von JS ist" - na ja, nicht genau. Dies ist ein perfektes Beispiel dafür.
Patrick

Antworten:

3

Leider ist dies derzeit in TypeScript nicht möglich. Wenn Sie mit einigen APIs zusammenarbeiten müssen, die dies erwarten oder wirklich Symbole als Schlüssel verwenden möchten, können Sie diese umständliche Version ausführen:

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