Saya ingin menyimpan pemetaan string -> string dalam objek naskah, dan menegakkan bahwa semua kunci memetakan ke string. Sebagai contoh:
var stuff = {};
stuff["a"] = "foo"; // okay
stuff["b"] = "bar"; // okay
stuff["c"] = false; // ERROR! bool != string
Apakah ada cara bagi saya untuk menegakkan bahwa nilai harus berupa string (atau tipe apa pun ..)?
typescript
Armentage
sumber
sumber
number
juga diizinkan sebagai tipe pengindeksantype Keys = 'Acceptable' | 'String' | 'Keys'
pengindeksan (kunci)?Di sini, antarmuka
AgeMap
memberlakukan kunci sebagai string, dan nilai sebagai angka. Kata kunciname
dapat berupa pengidentifikasi apa saja dan harus digunakan untuk menyarankan sintaks antarmuka / tipe Anda.Anda dapat menggunakan sintaksis yang serupa untuk memastikan bahwa suatu objek memiliki kunci untuk setiap entri dalam tipe gabungan:
Anda dapat, tentu saja, menjadikan ini tipe generik juga!
10.10.2018 pembaruan: Lihat jawaban @ dracstaxi di bawah ini - sekarang ada tipe bawaan
Record
yang melakukan sebagian besar untuk Anda.Pembaruan 1.2.2020: Saya sepenuhnya menghapus antarmuka pemetaan yang dibuat sebelumnya dari jawaban saya. @ dracstaxi jawaban membuat mereka sama sekali tidak relevan. Jika Anda masih ingin menggunakannya, periksa riwayat edit.
sumber
x = {}; x[1] = 2;
di Chrome kemudianObject.keys(x)
mengembalikan ["1"] danJSON.stringify(x)
mengembalikan '{"1": 2}'.Number
Kasing sudut dengan typeof (mis. Infinity, NaN, 1e300, 999999999999999999999 dll, dll) dapat dikonversi ke kunci string. Juga berhati-hatilah kasus sudut lain untuk kunci string sepertix[''] = 'empty string';
,x['000'] = 'threezeros';
x[undefined] = 'foo'
.Pembaruan cepat: karena Typefrip 2.1 ada tipe bawaan
Record<T, K>
yang berfungsi seperti kamus.Contoh dari dokumen:
TypeScript 2.1 Dokumentasi aktif
Record<T, K>
Satu-satunya kelemahan saya melihat ke menggunakan lebih ini
{[key: T]: K}
adalah bahwa Anda dapat mengkodekan info berguna pada jenis kunci yang Anda gunakan di tempat "kunci" misalnya jika objek Anda hanya memiliki kunci utama Anda bisa mengisyaratkan bahwa seperti:{[prime: number]: yourType}
.Berikut adalah regex yang saya tulis untuk membantu konversi ini. Ini hanya akan mengkonversi kasus di mana label adalah "kunci". Untuk mengonversi label lain cukup ubah grup penangkap pertama:
Temukan:
\{\s*\[(key)\s*(+\s*:\s*(\w+)\s*\]\s*:\s*([^\}]+?)\s*;?\s*\}
Menggantikan:
Record<$2, $3>
sumber
{}
?Record
s (tidak seperti, katakanlah, JavascriptMap
s) hanya menyediakan cara untuk menegakkan konten objek literal. Anda tidak bisanew Record...
danconst blah: Record<string, string>;
akan dikompilasi keconst blah;
.Record
:const isBroken: Record<"hat" | "teapot" | "cup", boolean> = { hat: false, cup: false, teapot: true };
Jawaban @Ryan Cavanaugh benar-benar baik dan masih valid. Masih layak untuk menambahkan bahwa pada Fall'16 ketika kita dapat mengklaim bahwa ES6 didukung oleh sebagian besar platform, hampir selalu lebih baik untuk tetap berpegang pada Peta setiap kali Anda perlu mengaitkan beberapa data dengan beberapa kunci.
Ketika kita menulis
let a: { [s: string]: string; }
kita perlu mengingat bahwa setelah naskah dikompilasi tidak ada yang namanya mengetik data, itu hanya digunakan untuk kompilasi. Dan {[s: string]: string; } akan dikompilasi menjadi hanya {}.Yang mengatakan, bahkan jika Anda akan menulis sesuatu seperti:
Ini tidak akan dikompilasi (bahkan untuk
target es6
, Anda akan mendapatkannyaerror TS1023: An index signature parameter type must be 'string' or 'number'.
Jadi praktis Anda dibatasi dengan string atau angka sebagai kunci potensial sehingga tidak ada banyak rasa menegakkan memeriksa jenis di sini, terutama mengingat bahwa ketika js mencoba mengakses kunci dengan angka itu mengubahnya menjadi string.
Jadi cukup aman untuk berasumsi bahwa praktik terbaik adalah menggunakan Peta bahkan jika kunci adalah string, jadi saya akan tetap dengan:
sumber
let dict: {[key in TrickyKey]: string} = {}
- di manaTrickyKey
jenis string literal (misalnya"Foo" | "Bar"
).Map
objek asli . Peta dilengkapi dengan overhead memori tambahan, dan (yang lebih penting) perlu dibuat secara manual dari setiap data yang disimpan sebagai string JSON. Mereka sering sangat berguna, tetapi tidak murni demi mendapatkan jenis dari mereka.Tentukan antarmuka
Menerapkan kunci untuk menjadi kunci spesifik antarmuka Pengaturan
sumber
Membangun jawaban @ shabunc, ini akan memungkinkan penegakan kunci atau nilai - atau keduanya - menjadi apa pun yang ingin Anda tegakkan.
Seharusnya juga berfungsi menggunakan
enum
bukantype
definisi.sumber