Tipe literal string dari array TypeScript


Saat ini saya memiliki baik array string maupun tipe union literal string yang berisi string yang sama:

const furniture = ['chair', 'table', 'lamp'];
type Furniture = 'chair' | 'table' | 'lamp';

Saya membutuhkan keduanya dalam aplikasi saya, tetapi saya mencoba menjaga kode saya tetap DRY. Jadi adakah cara untuk menyimpulkan salah satunya dari yang lain?

Saya pada dasarnya ingin mengatakan sesuatu seperti type Furniture=[setiap string dalam array furniture], sehingga tidak ada string yang duplikat.

Jawaban #1

TypeScript 3.4+

Dengan sintaks baru ini, kita mendapatkan solusi yang ringkas dan bagus ini:

const furniture = ['chair', 'table', 'lamp'] as const;
type Furniture = typeof furniture[number];

Lebih banyak tentang konteks const baru dapat ditemukan dalam PR ini serta di catatan rilis.

TypeScript 3.0+

Dengan penggunaan parameter rest generik, ada cara untuk secara benar menyimpulkan string[] sebagai tipe tuple literal dan kemudian mendapatkan tipe union dari literal tersebut.

Begini caranya:

const tuple = <T extends string[]>(...args: T) => args;
const furniture = tuple('chair', 'table', 'lamp');
type Furniture = typeof furniture[number];

Lebih lanjut tentang parameter istirahat generik

Jawaban #2

Jawaban ini sudah usang; lihat jawaban @ggradnig.

Solusi alternatif terbaik yang tersedia:

const furnitureObj = { chair: 1, table: 1, lamp: 1 };
type Furniture = keyof typeof furnitureObj;
const furniture = Object.keys(furnitureObj) as Furniture[];

Sebaiknya kita bisa melakukan ini:

const furniture = ['chair', 'table', 'lamp'];
type Furniture = typeof furniture[number];

Sayangnya, hari ini furniture ditafsirkan sebagai string[], yang berarti Furniture sekarang juga merupakan string.

Kita bisa menegakkan pengetikan sebagai literal dengan anotasi manual, tapi itu membawa kembali duplikasi:

const furniture = ["chair", "table", "lamp"] as ["chair", "table", "lamp"];
type Furniture = typeof furniture[number];

Masalah TypeScript #10195 melacak kemampuan untuk memberi petunjuk kepada TypeScript bahwa daftar tersebut harus disimpulkan sebagai tuple statis dan bukan string[], jadi mungkin di masa depan ini akan mungkin.

Jawaban #3

paling mudah di TypeScript 3.4: (catatan TypeScript 3.4 menambahkan konstanta assertions)

const furniture = ["chair", "table", "lamp"] as const;
type Furniture = typeof furniture[number]; // "chair" | "table" | "lamp"

juga lihat https://stackoverflow.com/a/55505556/4481226

atau jika Anda memiliki ini sebagai kunci dalam sebuah objek, Anda juga dapat mengubahnya menjadi sebuah union:

const furniture = {chair:{}, table:{}, lamp:{}} as const;
type Furniture = keyof typeof furniture; // "chair" | "table" | "lamp"

Artikel terkait