Katakanlah saya punya daftar
const list = ['a', 'b', 'c']
Apakah mungkin untuk diturunkan dari tipe serikat nilai ini 'a' | 'b' | 'c'
?
Saya menginginkan ini karena saya ingin menentukan tipe yang hanya mengizinkan nilai dari array statis, dan juga perlu menghitung nilai-nilai ini saat runtime, jadi saya menggunakan array.
Contoh bagaimana itu dapat diimplementasikan dengan objek yang diindeks:
const indexed = {a: null, b: null, c: null}
const list = Object.keys(index)
type NeededUnionType = keyof typeof indexed
Saya ingin tahu apakah mungkin melakukannya tanpa menggunakan peta yang diindeks.
typescript
WARNA PUTIH
sumber
sumber
Jawaban:
UPDATE Feb 2019
Dalam TypeScript 3.4, yang akan dirilis pada Maret 2019 , dimungkinkan untuk memberi tahu kompiler untuk menyimpulkan jenis tupel literal sebagai tupel literal , alih-alih sebagai, katakanlah
string[]
, dengan menggunakanas const
sintaks . Jenis pernyataan ini menyebabkan compiler menyimpulkan jenis sesempit mungkin untuk suatu nilai, termasuk membuat semuanyareadonly
. Ini akan terlihat seperti ini:const list = ['a', 'b', 'c'] as const; // TS3.4 syntax type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
Ini akan meniadakan kebutuhan akan fungsi pembantu apapun. Semoga berhasil lagi untuk semua!
UPDATE Juli 2018
Sepertinya, dimulai dengan TypeScript 3.0, TypeScript dapat menyimpulkan jenis tupel secara otomatis . Setelah dirilis,
tuple()
fungsi yang Anda butuhkan dapat ditulis secara ringkas sebagai:export type Lit = string | number | boolean | undefined | null | void | {}; export const tuple = <T extends Lit[]>(...args: T) => args;
Dan kemudian Anda bisa menggunakannya seperti ini:
const list = tuple('a','b','c'); // type is ['a','b','c'] type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
Harapan yang berhasil untuk orang-orang!
UPDATE Desember 2017
Sejak saya memposting jawaban ini, saya menemukan cara untuk menyimpulkan jenis tupel jika Anda ingin menambahkan fungsi ke perpustakaan Anda. Lihat fungsinya
tuple()
di tuple.ts . Dengan menggunakannya, Anda dapat menulis yang berikut dan tidak mengulangi diri Anda sendiri:const list = tuple('a','b','c'); // type is ['a','b','c'] type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
Semoga berhasil!
ASLI Juli 2017
Satu masalah adalah literal
['a','b','c']
akan disimpulkan sebagai tipestring[]
, sehingga sistem tipe akan melupakan nilai spesifiknya. Anda dapat memaksa sistem tipe untuk mengingat setiap nilai sebagai string literal:const list = ['a' as 'a','b' as 'b','c' as 'c']; // infers as ('a'|'b'|'c')[]
Atau, mungkin lebih baik, tafsirkan daftar tersebut sebagai jenis tupel:
const list: ['a','b','c'] = ['a','b','c']; // tuple
Ini adalah pengulangan yang mengganggu, tetapi setidaknya itu tidak memperkenalkan objek asing pada waktu proses.
Sekarang Anda bisa mendapatkan penyatuan Anda seperti ini:
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'.
Semoga membantu.
sumber
cont xs = ['a','b','c']; const list = tuple(...xs);
const xs = ['a','b','c']
, kompilator telah melebarxs
kestring[]
dan sepenuhnya melupakan nilai-nilai spesifik. Saya tidak dapat membantu perilaku itu setidaknya pada TS3.2 (mungkin adaas const
notasi masa depan yang berfungsi). Pokoknya saya pikir jawabannya masih benar karena saya bisa (saya sebutkan di sana yang['a','b','c']
disimpulkanstring[]
) jadi saya tidak yakin apa lagi yang Anda butuhkan.[number]
artinyalist[number]
?(typeof list)[number]
... tidaktypeof (list[number])
. TipeT[K]
adalah tipe pencarian yang mendapatkan tipe propertiT
yang kuncinya adalahK
. Di(typeof list)[number]
, Anda mendapatkan tipe properti dari(typeof list)
siapa kuncinyanumber
. Array sepertitypeof list
memiliki tanda tangan indeks numerik , sehingganumber
kuncinya menghasilkan gabungan dari semua properti yang diindeks secara numerik.Pembaruan untuk TypeScript 3.4:
Sintaks baru yang disebut "konteks const" yang akan tiba di TypeScript 3.4 akan memungkinkan solusi yang lebih sederhana yang tidak memerlukan panggilan fungsi seperti yang ditunjukkan. Fitur ini sedang ditinjau seperti yang terlihat di PR ini .
Singkatnya, sintaksis ini memungkinkan pembuatan array yang tidak dapat diubah yang memiliki tipe sempit (yaitu tipe,
['a', 'b', 'c']
bukan('a' | 'b' | 'c')[]
ataustring[]
). Dengan cara ini, kita dapat membuat tipe gabungan dari literal semudah yang ditunjukkan di bawah ini:const MY_VALUES = <const> ['a', 'b', 'c'] type MyType = typeof MY_VALUES[number]
Dalam sintaks alternatif:
const MY_VALUES = ['a', 'b', 'c'] as const type MyType = typeof MY_VALUES[number]
sumber
Ini tidak mungkin dilakukan dengan Array.
Alasannya adalah, meskipun Anda mendeklarasikan variabel sebagai const, konten array masih bisa berubah, sehingga @jonrsharpe menyebutkan ini adalah runtime.
Mengingat apa yang Anda inginkan, mungkin lebih baik digunakan
interface
dengankeyof
:interface X { a: string, b: string } type Y = keyof X // Y: 'a' | 'b'
Atau
enum
:sumber
a
lapangan ..Pick<T, U>
untuk itu.