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

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,即使某些东西看起来可能是null,它也可以相信你它不是:

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

其他回答

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

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

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

你试图设置变量name1,女巫类型设置为严格的字符串(它必须是字符串),值从对象字段名,女巫值类型设置为可选字符串(它可以是字符串或未定义,因为问题符号)。如果你真的需要这种行为,你必须像这样改变name1的类型:

let name1: string | undefined = person.name;

一切都会好的;

我认为使用Karol Majewski提到的Require非常好。另一种实现相同的方法是使用交集类型(实际上由Require在内部使用)

function getPerson(): Person & {name: string} {
  const person = {name:"John"};
  return person;
}

const person = getPerson();
const name1: string = person.name;

使用Require或交集类型的优点是,我们不会像非空断言操作符那样推翻typescript编译器。

如果你从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!;