Typescript: Tipe 'string | undefined' tidak dapat ditetapkan ke tipe 'string'


Ketika saya membuat properti dari sebuah antarmuka menjadi opsional, dan saat menetapkan anggotanya ke variabel lain seperti ini:

interface Person {
  name?: string,
  age?: string,
  gender?: string,
  occupation?: string,
}

function getPerson() {
  let person = <Person>{name:"John"};
  return person;
}

let person: Person = getPerson();
let name1: string = person.name; // <<< Error here 

Saya mendapatkan kesalahan seperti berikut:

TS2322: Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.

Bagaimana saya bisa mengatasi kesalahan ini?

Jawaban #1

Anda sekarang dapat menggunakan operator pengecekan non-null yang ada di sini tepat untuk kasus penggunaan Anda.

Ini memberi tahu TypeScript bahwa meskipun sesuatu terlihat seperti bisa bernilai null, ia bisa mempercayai Anda bahwa itu tidak:

let name1:string = person.name!; 
//                            ^ note the exclamation mark here  

Jawaban #2

Saya tahu ini agak terlambat, tetapi cara lain selain jawaban Yannick untuk menggunakan ! adalah dengan mengubahnya menjadi string sehingga memberi tahu TypeScript: Saya yakin ini adalah string, sehingga mengubahnya.

let name1:string = person.name; // Error here compile time

ke

let name1 = person.name as string; // No error here compile time, runtime though

Ini akan membuat kesalahan hilang, tetapi jika kebetulan ini bukan string, Anda akan mendapatkan kesalahan saat menjalankan program... yang merupakan salah satu alasan kami menggunakan TypeScript untuk memastikan tipe cocok dan menghindari kesalahan seperti itu saat waktu kompilasi.

Jawaban #3

Untuk menghindari kesalahan kompilasi saya menggunakan

let name1:string = person.name || '';

Dan kemudian validasi string kosong.

Jawaban #4

Sejak TypeScript 3.7 Anda dapat menggunakan operator penggabungan null ??. Anda dapat menganggap fitur ini sebagai cara untuk "kembali" ke nilai default saat menangani null atau undefined

let name1:string = person.name ?? '';

Operator ?? dapat menggantikan penggunaan || saat mencoba menggunakan nilai default dan dapat digunakan ketika menangani boolean, angka, dll. di mana || tidak dapat digunakan.

Mulai TypeScript 4, Anda bisa menggunakan operator penugasan ??= seperti a ??= b yang merupakan alternatif dari a=a ?? b;

Jawaban #5

Menurut definisi Anda Person.name bisa null tetapi name1 tidak bisa. Ada dua skenario:

Person.name tidak pernah null

beri tahu kompiler bahwa Anda yakin nama itu tidak null dengan menggunakan !

let name1: string = person.name!;

Person.name bisa bernilai null

tentukan nilai default jika nama bernilai null

let name1: string = person.name ?? "default name";

Jawaban #6

Cara yang lebih siap untuk produksi dalam menangani ini adalah dengan benar-benar memastikan bahwa name ada. Dengan asumsi ini adalah contoh minimal dari proyek yang lebih besar di mana sekelompok orang terlibat, Anda tidak tahu bagaimana getPerson akan berubah di masa depan.

if (!person.name) {
    throw new Error("Unexpected error: Missing name");
}

let name1: string = person.name;

Sebagai alternatif, Anda dapat mengetik name1 sebagai string | undefined, dan menangani kasus undefined lebih jauh. Namun, biasanya lebih baik menangani kesalahan tak terduga lebih awal.

Anda juga dapat membiarkan TypeScript menyimpulkan tipe dengan menghilangkan tipe yang eksplisit: let name1=person.name Ini tetap akan mencegah name1 diubah menjadi angka, misalnya.

Jawaban #7

Berikut cara cepat untuk mengetahui apa yang sedang terjadi:

Ketika kamu melakukan hal berikut:

nama? : string

Anda mengatakan kepada TypeScript bahwa itu opsional. Namun, ketika Anda melakukannya:

let name1 : string = person.name; //<<<Error here 

Anda tidak memberinya pilihan. Anda perlu memiliki Union pada itu yang mencerminkan tipe yang tidak terdefinisi:

let name1 : string | undefined = person.name; //<<<No error here 

Dengan menggunakan jawaban Anda, saya dapat membuat sketsa berikut yang pada dasarnya adalah sebuah Interface, sebuah Kelas, dan sebuah Objek. Saya menemukan pendekatan ini lebih sederhana, tidak masalah jika Anda tidak.

// Interface
interface iPerson {
    fname? : string,
    age? : number,
    gender? : string,
    occupation? : string,
    get_person?: any
}

// Class Object
class Person implements iPerson {
    fname? : string;
    age? : number;
    gender? : string;
    occupation? : string;
    get_person?: any = function () {
        return this.fname;
    }
}

// Object literal
const person1 : Person = {
    fname : 'Steve',
    age : 8,
    gender : 'Male',
    occupation : 'IT'  
}

const p_name: string | undefined = person1.fname;

// Object instance 
const person2: Person = new Person();
person2.fname = 'Steve';
person2.age = 8;
person2.gender = 'Male';
person2.occupation = 'IT';

// Accessing the object literal (person1) and instance (person2)
console.log('person1 : ', p_name);
console.log('person2 : ', person2.get_person());

Jawaban #8

cobalah untuk mengetahui nilai sebenarnya sebelumnya. Jika person memiliki name yang valid, tetapkan ke name1, jika tidak tetapkan undefined.

let name1: string = (person.name) ? person.name : undefined;

Artikel terkait