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


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.