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

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

如何避免这个错误呢?


当前回答

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

Person.name从不为空

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

let name1: string = person.name!;

Person.name可以为空

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

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

其他回答

为了避免我使用的编译错误

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

然后验证空字符串。

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

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

这是我发现的检查属性是否未定义而不生成警告的唯一解决方案

type NotUndefined<T, K extends keyof T> = T & Record<K, Exclude<T[K], undefined>>;
function checkIfKeyIsDefined<T, K extends keyof T>(item: T, key: K): item is NotUndefined<T, K> {
    return typeof item === 'object' && item !== null && typeof item[key] !== 'undefined';
}

用法:


interface Listing { 
    order?: string
    ...
}
obj = {..., order: 'pizza'} as Listing
if(checkIfKeyIsDefined(item: obj, 'order')) {
    order.toUpperCase() //no undefined warning O.O
}

原来的答案

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

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

Person.name从不为空

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

let name1: string = person.name!;

Person.name可以为空

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

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