当我将接口的任何属性设置为可选时,并将其成员分配给其他变量,如下所示:
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
我得到如下错误:
TS2322: Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
如何避免这个错误呢?
解决方案1:删除显式类型定义
因为getPerson已经返回了一个带有名称的Person,所以我们可以使用推断类型。
function getPerson(){
let person = {name:"John"};
return person;
}
let person = getPerson();
如果我们定义person: person,我们将丢失一条信息。我们知道getPerson返回一个具有非可选属性name的对象,但是将其描述为Person会使可选性恢复。
解决方案2:使用更精确的定义
type Require<T, K extends keyof T> = T & {
[P in K]-?: T[P]
};
function getPerson() {
let person = {name:"John"};
return person;
}
let person: Require<Person, 'name'> = getPerson();
let name1:string = person.name;
解决方案3:重新设计界面
所有属性都是可选的形状称为弱类型,通常是设计不好的标志。如果我们将name作为必需属性,那么您的问题就解决了。
interface Person {
name:string,
age?:string,
gender?:string,
occupation?:string,
}
如果你从getPerson函数中移除<Person>强制转换,那么TypeScript将足够聪明地检测到你返回的对象确实具有name属性。
所以只要转一下:
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;
成:
interface Person {
name?: string,
age?: string,
gender?: string,
occupation?: string,
}
function getPerson() {
let person = {name: 'John'};
return person;
}
let person = getPerson();
let name1: string = person.name;
如果你不能这样做,那么你将不得不使用@yannick1976建议的“确定赋值断言操作符”:
let name1: string = person.name!;