Eksperimen: Jadikan TypeScript tidak dapat diubah secara default – Beragampengetahuan
Saya suka bahasa pemrograman yang variabelnya tidak dapat diubah secara default. Misalnya, di Rust, let Deklarasikan variabel yang tidak dapat diubah dan let mut Deklarasikan suatu hal yang bisa berubah. Saya berharap dapat mencapai ini dalam bahasa lain, seperti TypeScript, yang dapat diubah secara default – yang merupakan kebalikan dari keinginan saya!
Saya ingin tahu: Apakah mungkin untuk membuat nilai-nilai TypeScript tidak dapat diubah secara default?
Tujuan saya adalah melakukan ini murni menggunakan TypeScript, tanpa mengubah TypeScript itu sendiri. Ini berarti tidak ada aturan lint atau alat lainnya. Saya memilih ini karena saya ingin solusinya semurni mungkin… dan kedengarannya juga lebih menarik.
Saya menghabiskan malam mencoba melakukan ini. Saya gagal, tetapi membuat kemajuan! Saya melakukan array dan RecordSecara default, ini tidak dapat diubah, tetapi saya tidak bisa membuatnya berfungsi dengan objek biasa. Jika Anda mengetahui cara melakukan ini, silakan hubungi saya – saya perlu tahu!
Contents
Langkah 1: Hapus perpustakaan bawaan
TypeScript memiliki definisi tipe bawaan untuk API JavaScript, seperti Array Dan Date Dan String. jika kamu pernah berubah target atau lib Pada opsi di TSConfig, Anda telah menyesuaikan definisi mana yang disertakan. Misalnya, jika Anda menargetkan runtime yang lebih baru, Anda dapat menambahkan pustaka “ES2024”.
Tujuan saya adalah mengganti perpustakaan bawaan dengan perpustakaan pengganti yang tidak dapat diubah secara default.
Langkah pertama adalah berhenti menggunakan perpustakaan bawaan apa pun. saya mengatur noLib Tandai di TSConfig saya seperti ini:
"compilerOptions":
"noLib": true
Kemudian saya menulis skrip yang sangat sederhana dan memasukkannya ke dalamnya test.ts:
console.log("Hello world!");
saat aku berlari tscini memberikan banyak kesalahan:
Cannot find global type 'Array'.
Cannot find global type 'Boolean'.
Cannot find global type 'Function'.
Cannot find global type 'IArguments'.
Cannot find global type 'Number'.
Cannot find global type 'Object'.
Cannot find global type 'RegExp'.
Cannot find global type 'String'.
kemajuan! Saya telah berhasil menghapus semua perpustakaan TypeScript default, saya dapat mengatakan itu karena tidak dapat menemukan tipe inti seperti ini String atau Boolean.
Saatnya menulis penggantinya.
Langkah 2: Kerangka perpustakaan standar
Proyek ini adalah prototipe. Jadi saya mulai dengan solusi minimal yang melakukan pengecekan tipe. Saya tidak membutuhkannya untuk menjadi baik!
saya buat lib.d.ts dan masukkan yang berikut ke dalamnya:
// In lib.d.ts:
declare var console: any;
interface Boolean
interface Function
interface IArguments
interface Number
interface RegExp
interface String
interface Object
// TODO: We'll update this soon.
interface Array<T>
Sekarang saat aku berlari tscsaya tidak membuat kesalahan! Saya mendefinisikan semua tipe bawaan yang dibutuhkan TypeScript, serta tipe virtual console Tujuan.
Seperti yang Anda lihat, solusi ini tidak praktis untuk produksi. Pertama, tidak satu pun dari antarmuka ini yang memiliki properti apa pun! "foo".toUpperCase() Misalnya, tidak terdefinisi. Tidak apa-apa karena ini hanya prototipe. Versi siap produksi perlu mendefinisikan semua hal ini – yang membosankan, namun harus jelas.
Langkah 3: Jadikan array tidak dapat diubah
Saya memutuskan untuk menggunakan gaya pengembangan berbasis pengujian untuk mengatasi masalah ini. Saya akan menulis beberapa kode yang ingin saya ketik, periksa dan tonton gagal Lakukan pengecekan tipe, lalu perbaiki.
Saya memperbarui test.ts Berisi konten berikut:
// In test.ts:
const arr = [1, 2, 3];
// Non-mutation should be allowed.
console.log(arr[1]);
console.log(arr.map((n) => n + 1));
// @ts-expect-error Mutation should not be allowed.
arr[0] = 9;
// @ts-expect-error Mutation should not be allowed.
arr.push(4);
Ini menguji tiga hal:
- Array dapat dibuat menggunakan literal array.
- Operasi yang tidak bermutasi, mis.
arr[1]Danarr.map()diperbolehkan. - Operasi yang mengubah array, seperti
arr[1] = 9tidak diperbolehkan.
saat aku berlari tscsaya melihat dua kesalahan:
arr[0] = 9diperbolehkan. Ada satu yang belum terpakai@ts-expect-errorDi sana.arr.mapTidak ada.
Jadi saya memperbarui Array memasuki lib.d.ts Memiliki konten berikut:
// In lib.d.ts:
interface Array<T>
readonly [n: number]: T;
map<U>(
callbackfn: (value: T, index: number, array: readonly T[]) => U,
thisArg?: any
): U[];
Pengakses properti – readonly [n: number]: T baris—Memberitahukan TypeScript bahwa Anda dapat mengakses properti array berdasarkan indeks numerik, tetapi properti tersebut hanya dapat dibaca. itu seharusnya berhasil arr[1] mungkin tapi arr[1] = 9 Mustahil.
ini map Definisi metode disalin dari kode sumber TypeScript tanpa perubahan apa pun (kecuali untuk beberapa pemformatan otomatis). Ini harusnya bisa menelepon arr.map().
Harap dicatat bahwa saya melakukannya TIDAK definisi push. Kita tidak boleh menyebutnya pada array yang tidak dapat diubah!
saya berlari tsc Sukses lagi! Tidak ada kesalahan! Kami sekarang memiliki array yang tidak dapat diubah!
Pada tahap ini saya telah menunjukkannya TypeScript dapat dikonfigurasi untuk membuat semua array tidak dapat diubah tanpa anotasi tambahan. tidak perlu readonly string[] atau ReadonlyArray<number>! Dengan kata lain, kita menetapkan tingkat kekekalan tertentu secara default.
Kode ini, seperti semua yang ada di artikel ini, sangat sederhana. Ada banyak metode array lainnya, seperti filter() Dan join() Dan forEach()! Jika ini sudah siap produksi, saya akan memastikan semua metode array read-only telah ditentukan.
Tapi sekarang, saya siap untuk pindah ke array yang bisa berubah.
Langkah 4: Array Variabel
Saya lebih suka kekekalan, tapi terkadang saya ingin bisa mendefinisikan array yang bisa berubah. Jadi saya membuat test case lain:
// In test.ts:
const arr = [1, 2, 3] as MutableArray<number>;
arr[0] = 9;
arr.push(4);
Perhatikan bahwa ini memerlukan kerja ekstra untuk membuat array bisa berubah. Dengan kata lain, ini bukan nilai default.
TypeScript mengeluh bahwa itu tidak dapat ditemukan MutableArrayjadi saya mendefinisikannya:
// In lib.d.ts:
interface MutableArray<T> extends Array<T>
[n: number]: T;
push(...items: T[]): number;
Ketik pemeriksaan pass lagi!
Sekarang, saya memiliki array yang bisa berubah dan tidak bisa diubah, tidak bisa diubah secara default. Sekali lagi, ini sederhana, namun cukup baik sebagai bukti konsep!
Ini membuatku bersemangat. TypeScript dapat dikonfigurasi agar tidak dapat diubah secara default, setidaknya untuk array. Saya tidak perlu mengubah bahasa atau menggunakan alat lain apa pun.
Bisakah saya membuat lebih banyak hal tidak dapat diubah?
Langkah 5: Sama Record
Saya ingin melihat apakah saya bisa melampaui array. Tujuan saya selanjutnya adalah Record type, yang merupakan tipe utilitas TypeScript. Jadi saya mendefinisikan sepasang kasus uji lainnya, mirip dengan apa yang saya lakukan untuk array:
// In test.ts:
// Immutable records
const obj1: Record<string, string> = foo: "bar" ;
console.log(obj1.foo);
// @ts-expect-error Mutation should not be allowed.
obj1.foo = "baz";
// Mutable records
const obj2: MutableRecord<string, string> = foo: "bar" ;
obj2.foo = "baz";
TypeScript mengeluh bahwa itu tidak dapat ditemukan Record atau MutableRecord. Ia juga mengeluh karena tidak menggunakan @ts-expect-erroryang berarti mutasi diperbolehkan.
Saya menyingsingkan lengan baju saya dan memperbaiki kesalahan ini sebagai berikut:
// In lib.d.ts:
declare type PropertyKey = string | number | symbol;
type Record<KeyT extends PropertyKey, ValueT> =
readonly [key in KeyT]: ValueT;
;
type MutableRecord<KeyT extends PropertyKey, ValueT> =
[key in KeyT]: ValueT;
;
Sekarang, kita punya Recordyang merupakan pasangan nilai kunci yang tidak dapat diubah dan juga versi yang dapat diubah. Sama seperti sebuah array!
Anda dapat membayangkan memperluas ide ini ke tipe bawaan lainnya, misalnya. Set Dan Map. Saya pikir akan mudah untuk melakukan ini seperti dengan array dan catatan. Saya akan menyerahkannya sebagai latihan kepada pembaca.
Langkah 6 gagal: objek normal
Tes terakhir saya adalah membuat objek biasa (bukan catatan atau array) tidak dapat diubah. Sayangnya bagi saya, saya tidak dapat memahaminya.
Ini adalah test case yang saya tulis:
// In test.ts:
const obj = foo: "bar" ;
console.log(obj.foo);
// @ts-expect-error Mutation should not be allowed.
obj.foo = "baz";
Ini membuatku bingung. Apa pun yang saya lakukan, saya tidak dapat menulis tipe yang tidak mengizinkan mutasi ini. Saya mencoba memodifikasi Object Saya mengetiknya dengan segala cara yang terpikirkan oleh saya, namun tetap tidak berhasil!
Metode anotasi meliputi obj Jadikan itu tidak bisa diubah, tapi itu tidak sesuai dengan semangat tujuan saya. Saya berharap ini tidak dapat diubah secara default!
Sayangnya, di sinilah saya menyerah.
Bisakah kamu mengetahuinya?
Saya ingin TypeScript tidak dapat diubah secara default. Saya bisa melakukan ini dengan array, Records, serta tipe lain seperti Map Dan Set. Sayangnya saya tidak bisa membuatnya berfungsi untuk definisi objek sederhana seperti obj = foo: "bar" .
Mungkin ada cara untuk menerapkan hal ini melalui aturan lint, dengan melarang operasi mutasi, atau mewajibkannya Readonly Ada catatan di mana-mana. Saya ingin melihat seperti apa rasanya.
jika Anda Cari tahu cara membuat TypeScript tidak dapat diubah secara default tidak ada alat lainsaya ingin mengetahuinya dan saya akan memperbarui postingan saya. Saya berharap upaya saya yang gagal dapat membawa orang lain menuju kesuksesan.
Sekali lagi, jika Anda memecahkan masalah ini, atau punya ide lain, silakan hubungi saya.
rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#Eksperimen #Jadikan #TypeScript #tidak #dapat #diubah #secara #default