当我将接口的任何属性设置为可选时,并将其成员分配给其他变量,如下所示:

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'.

如何避免这个错误呢?


当前回答

从TypeScript 3.7开始,你可以使用空合并运算符??您可以将此特性视为在处理null或未定义时“退回”到默认值的一种方式

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

的? ?当尝试使用默认值时,操作符可以替换||的使用,并且可以在处理不能使用||的布尔值、数字等时使用。

从TypeScript 4开始,你可以使用??=赋值运算符作为??= b是a = a的替代??b;

其他回答

根据您的定义,Person.name可以为空,但name1不能。 有两种情况:

Person.name从不为空

告诉编译器你确定名称不是空的使用!

let name1: string = person.name!;

Person.name可以为空

在case name为null时指定一个默认值

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

试着事先找出实际值。如果person有一个有效的名称,则将其赋值给name1,否则赋值为undefined。

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

从TypeScript 3.7开始,你可以使用空合并运算符??您可以将此特性视为在处理null或未定义时“退回”到默认值的一种方式

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

的? ?当尝试使用默认值时,操作符可以替换||的使用,并且可以在处理不能使用||的布尔值、数字等时使用。

从TypeScript 4开始,你可以使用??=赋值运算符作为??= b是a = a的替代??b;

解决方案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,
}

也有同样的问题。

我发现react-scrips添加了“strict”:true到tsconfig.json。

在我移除它之后,一切都很好。

Edit

需要警告的是,更改此属性意味着:

不再对潜在的运行时错误发出警告。

正如保罗在评论中指出的那样!谢谢!

只有在你完全理解它的影响时才使用"strict": false !