Menggunakan simbol sebagai tipe objek-kunci dalam TypeScript

20

Saya mencoba mendefinisikan objek dengan simbol sebagai tipe kunci sejak MDN mengatakan:

Nilai simbol dapat digunakan sebagai pengidentifikasi untuk properti objek [...]

Tetapi menggunakannya sebagai tipe untuk properti-kunci:

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

mengakibatkan kesalahan berikut:

TS1023: Jenis parameter tanda tangan indeks harus berupa 'string' atau 'angka'.

bahkan dapat digunakan sebagai tipe indeks. Saya menggunakan versi naskah terbaru ( v3.7.2), pertanyaan terkait yang saya temukan:

Saya juga telah melihat dokumen simbol naskah tetapi mereka hanya menunjukkan bagaimana itu digunakan sebagai nilai, bukan sebagai jenis.

Contoh:

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

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

Masalah pada Microsoft / TypeScript

Buka permintaan fitur

Simon
sumber
Saya pikir TypeScript hanya mendukung simbol spesifik dalam deklarasi tipe objeknya. Apakah Anda benar-benar ingin setiap symbol ? Mungkin tunjukkan contoh bagaimana Anda ingin menggunakan milik Anda type obj- Saya ragu bahwa semua properti dengan kunci simbol adalah strings.
Bergi
@Bergi Saya telah menambahkan contoh, mungkin saya telah mengawasi sesuatu tetapi saya tidak dapat menemukan cara untuk membawa ts menerima simbol (tanpa menggunakan anyyang merupakan praktik buruk).
Simon
Saya tidak yakin apakah saya benar tetapi apakah Anda mencoba menggunakan Map<Symbol,String>karena kami memiliki Peta, jika itu akan melayani tujuan dari apa yang Anda coba capai
pavan kumar
Masalah yang sama bagi saya, saya kira bagian yang mengganggu adalah iklan palsu tentang bagaimana "TS adalah superset dari JS" - well, tidak persis. ini adalah contoh sempurna untuk itu.
Patrick

Jawaban:

3

Sayangnya ini tidak mungkin saat ini dalam TypeScript. Jika Anda harus beroperasi dengan beberapa API yang mengharapkan ini atau benar - benar ingin menggunakan simbol sebagai kunci, Anda dapat melakukan versi canggung ini:

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