Typescript: Tip 'string | undefined' nije dodjeljiv tipu 'string'
Kada učinim bilo koju svojinu sučelja opcionalnom, i dok dodjeljujem njegov član nekoj drugoj varijabli na ovaj način:
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
Dobijem pogrešku poput sljedeće:
TS2322: Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
Kako da zaobiđem ovu grešku?
Odgovor #1
Sada možete koristiti operator nepotvrđene vrijednosti koji je ovdje upravo za vaš slučaj upotrebe.
Kaže TypeScriptu da, iako nešto izgleda kao da bi moglo biti null, može vam vjerovati da nije:
let name1:string = person.name!;
// ^ note the exclamation mark here
Odgovor #2
Znam da je ovo pomalo kasno, ali drugi način osim Yannickovog odgovora za korištenje ! je da ga pretvorite u string, čime TypeScriptu kažete: Siguran sam da je ovo string, čime ga pretvarate.
let name1:string = person.name; // Error here compile time
to
let name1 = person.name as string; // No error here compile time, runtime though
Ovo će ukloniti grešku, ali ako slučajno ovo nije string, dobit ćete pogrešku tijekom izvođenja... što je jedan od razloga zbog kojih koristimo TypeScript kako bismo osigurali da se tip podudara i izbjegli takve pogreške već tijekom kompajliranja.
Odgovor #3
Kako bih izbjegao pogrešku pri kompilaciji, koristio sam
let name1:string = person.name || '';
A zatim provjerite prazni niz.
Odgovor #4
Od TypeScript 3.7 možete koristiti operator spajanja s null vrijednošću ??. Možete razmišljati o ovoj funkciji kao načinu da se „vratite“ na zadanu vrijednost kada radite s null ili undefined.
let name1:string = person.name ?? '';
Operator ?? može zamijeniti korištenje || kada pokušavate koristiti zadanu vrijednost i može se koristiti pri radu s booleovima, brojevima itd., gdje || ne može biti korišten.
Od TypeScripta 4 možete koristiti operator dodjele ??= kao a ??= b, što je alternativa za a=a ?? b;
Odgovor #5
Prema vašoj definiciji Person.name može biti null, ali name1 ne može. Postoje dva scenarija:
Person.name nikada nije null
reci prevoditelju da si siguran da ime nije null koristeći !
let name1: string = person.name!;
Person.name može biti null
navedite zadanu vrijednost u slučaju da je ime null
let name1: string = person.name ?? "default name";
Odgovor #6
Proizvodno spremniji način za rukovanje ovim je zapravo osigurati da name postoji. Pretpostavljajući da je ovo minimalni primjer većeg projekta u kojem je uključena grupa ljudi, ne znate kako će se getPerson mijenjati u budućnosti.
if (!person.name) {
throw new Error("Unexpected error: Missing name");
}
let name1: string = person.name;
Alternativno, možete unijeti name1 kao string | undefined i kasnije se pobrinuti za slučajeve undefined. Međutim, obično je bolje rukovati neočekivanim pogreškama ranije.
Također možete dopustiti TypeScriptu da zaključi tip izostavljanjem eksplicitnog tipa: let name1=person.name To će i dalje spriječiti da se name1 ponovno dodijeli kao broj, na primjer.
Odgovor #7
Evo brzog načina da saznate što se događa:
Kada si učinio sljedeće:
ime? : string
Govorio si TypeScriptu da je to opcionalno. Ipak, kada si napravio:
let name1 : string = person.name; //<<<Error here
Nisi mu dao izbor. Trebalo je imati Uniju na tome koja odražava neodređeni tip:
let name1 : string | undefined = person.name; //<<<No error here
Korištenjem vašeg odgovora, uspio sam nacrtati sljedeće što je u osnovi sučelje, klasa i objekt. Smatram ovaj pristup jednostavnijim, bez obzira ako vi ne mislite tako.
// 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());
Odgovor #8
pokušajte unaprijed saznati koja je stvarna vrijednost. Ako person ima valjani name, dodijelite ga name1, inače dodijelite undefined.
let name1: string = (person.name) ? person.name : undefined;
