Ada beberapa situasi yang akan memberi Anda kesalahan khusus ini. Dalam kasus OP ada nilai yang didefinisikan secara eksplisit sebagai string . Jadi saya harus berasumsi bahwa mungkin ini berasal dari dropdown, atau layanan web atau string JSON mentah.
Dalam hal ini pemeran sederhana <Fruit> fruitString
atau fruitString as Fruit
satu-satunya solusi (lihat jawaban lain). Anda tidak akan pernah bisa memperbaiki ini pada waktu kompilasi. [ Sunting: Lihat jawaban saya yang lain tentang<const>
]!
Namun sangat mudah untuk mengalami kesalahan yang sama ketika menggunakan konstanta dalam kode Anda yang tidak pernah dimaksudkan untuk menjadi tipe string . Jawaban saya berfokus pada skenario kedua:
Pertama-tama: Mengapa konstanta string 'ajaib' seringkali lebih baik daripada enum?
- Saya suka cara string konstan terlihat vs enum - itu kompak dan 'javascripty'
- Lebih masuk akal jika komponen yang Anda gunakan sudah menggunakan konstanta string.
- Harus mengimpor 'tipe enum' hanya untuk mendapatkan nilai enumerasi bisa menyusahkan
- Apa pun yang saya lakukan, saya ingin kompilasi aman jadi jika saya menambahkan hapus nilai yang valid dari jenis gabungan, atau salah ketik maka itu HARUS memberikan kesalahan kompilasi.
Untungnya saat Anda mendefinisikan:
export type FieldErrorType = 'none' | 'missing' | 'invalid'
... Anda benar-benar mendefinisikan penyatuan jenis mana 'missing'
sebenarnya merupakan tipe!
Saya sering mengalami kesalahan 'tidak dapat ditugaskan' jika saya memiliki string seperti 'banana'
dalam naskah saya dan berpikir kompiler saya maksudkan sebagai string, sedangkan saya benar-benar ingin itu menjadi tipe banana
. Seberapa pintar kompiler dapat bergantung pada struktur kode Anda.
Berikut adalah contoh ketika saya mendapat kesalahan ini hari ini:
// this gives me the error 'string is not assignable to type FieldErrorType'
fieldErrors: [ { fieldName: 'number', error: 'invalid' } ]
Segera setelah saya menemukan itu 'invalid'
atau 'banana'
bisa berupa tipe atau string, saya menyadari bahwa saya hanya bisa menegaskan string ke tipe itu . Pada dasarnya melemparkannya ke dirinya sendiri , dan katakan kompiler tidak, saya tidak ingin ini menjadi string !
// so this gives no error, and I don't need to import the union type too
fieldErrors: [ { fieldName: 'number', error: <'invalid'> 'invalid' } ]
Jadi apa yang salah dengan 'casting' untuk FieldErrorType
(atau Fruit
)
// why not do this?
fieldErrors: [ { fieldName: 'number', error: <FieldErrorType> 'invalid' } ]
Ini bukan waktu kompilasi yang aman:
<FieldErrorType> 'invalidddd'; // COMPILER ALLOWS THIS - NOT GOOD!
<FieldErrorType> 'dog'; // COMPILER ALLOWS THIS - NOT GOOD!
'dog' as FieldErrorType; // COMPILER ALLOWS THIS - NOT GOOD!
Mengapa? Ini adalah naskah jadi <FieldErrorType>
adalah pernyataan dan Anda memberi tahu kompiler bahwa anjing adalah FieldErrorType ! Dan kompiler akan mengizinkannya!
TETAPI jika Anda melakukan hal berikut, maka kompiler akan mengubah string menjadi tipe
<'invalid'> 'invalid'; // THIS IS OK - GOOD
<'banana'> 'banana'; // THIS IS OK - GOOD
<'invalid'> 'invalidddd'; // ERROR - GOOD
<'dog'> 'dog'; // ERROR - GOOD
Berhati-hatilah terhadap kesalahan ketik bodoh seperti ini:
<'banana'> 'banan'; // PROBABLY WILL BECOME RUNTIME ERROR - YOUR OWN FAULT!
Cara lain untuk memecahkan masalah adalah dengan melemparkan objek induk:
Definisi saya adalah sebagai berikut:
jenis ekspor FieldName = 'angka' | | 'Tanggal kadaluwarsa' | 'cvv'; jenis ekspor FieldError = 'tidak ada' | 'hilang' | 'tidak valid'; jenis ekspor FieldErrorType = {bidang: FieldName, kesalahan: FieldError};
Katakanlah kita mendapatkan kesalahan dengan ini (string tidak dapat ditugaskan kesalahan):
fieldErrors: [ { field: 'number', error: 'invalid' } ]
Kita dapat 'menegaskan' seluruh objek sebagai FieldErrorType
berikut:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]
Maka kita menghindari keharusan melakukannya <'invalid'> 'invalid'
.
Tapi bagaimana dengan kesalahan ketik? Tidak <FieldErrorType>
hanya menegaskan apa pun yang berhak menjadi tipe itu. Tidak dalam kasus ini - untungnya kompiler AKAN mengeluh jika Anda melakukan ini, karena cukup pintar untuk mengetahui bahwa itu tidak mungkin:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]
export type Fruit
?