web-dev-qa-db-ja.com

TypeScriptでオブジェクトキータイプとしてシンボルを使用する

MDNが言うので、キータイプとして symbol を使用してオブジェクトを定義しようとしています:

シンボル値は、オブジェクトプロパティの識別子として使用できます[...]

ただし、キープロパティのタイプとして使用します。

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

次のエラーが発生します。

TS1023:インデックスシグネチャのパラメータータイプは、 'string'または 'number'でなければなりません。

それでもインデックスタイプとして使用できます。私は最新のTypeScriptバージョン(v3.7.2)、私が見つけた関連質問:

TypeScriptシンボルのドキュメント も確認しましたが、タイプとしてではなく、値としての使用方法のみを示しています。

例:

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

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

Microsoft/TypeScriptの問題

オープン機能リクエスト

19
Simon

残念ながら、現時点ではTypeScriptではこれは不可能です。これを期待するいくつかのAPIと相互運用する必要がある場合、またはreallyがシンボルをキーとして使用したい場合、この厄介なバージョンを実行できます。

// 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
2
Dmitriy