当我将接口的任何属性设为可选时,将其成员分配给其他变量时出现如下错误
TS2322:键入“字符串| 未定义”不能分配给“字符串”类型。类型“未定义”不能分配给类型“字符串”。
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 
如何解决此错误?
Har*_*rry 74
我知道这有点晚了,但是除了yannick使用的答案之外的另一种方法!是将其转换为 string 从而告诉 TypeScript:我确定这是一个 string,因此将其转换。
let name1:string = person.name;//<<<Error here 
到
let name1:string = person.name as string;
这将使错误消失,但如果有任何机会这不是字符串,您将收到运行时错误......这是我们使用 TypeScript 来确保类型匹配并避免此类错误的原因之一编译时间。
igo*_*igo 45
从 TypeScript 3.7 开始,您可以使用空合并运算符 ??。您可以将此功能视为在处理 null 或 undefined 时“回退”到默认值的一种方式
let name1:string = person.name ?? '';
该??操作可替代的用途||尝试使用默认值,并且可以与布尔值,数字等,其中处理时,可以使用时,||不能使用。
从 TypeScript 4 开始,您可以使用??=赋值运算符作为a ??= b替代a = a ?? b;
yan*_*976 35
现在,您可以使用恰好适合您的用例的非null断言运算符。
它告诉TypeScript即使某些内容看起来可能为null,也可以相信它不是:
let name1:string = person.name!; 
//                            ^ note the exclamation mark here  
And*_*ine 19
为了避免我使用的编译错误
let name1:string = person.name || '';
然后验证空字符串。
gol*_*ins 13
处理此问题的一种更适合生产的方法是实际确保name存在。假设这是一群人参与的大型项目的最小示例,您不知道getPerson将来会发生怎样的变化。
if (!person.name) {
    throw new Error("Unexpected error: Missing name");
}
let name1: string = person.name;
或者,您可以输入name1as string | undefined,然后处理undefined更进一步的情况。但是,提前处理意外错误通常会更好。
您还可以通过省略显式类型让 TypeScript 推断类型:例如,let name1 = person.name这仍将防止name1被重新分配为数字。
这是了解正在发生的事情的快速方法:
当您执行以下操作时:
姓名?: 细绳
你对 TypeScript 说它是可选的。然而,当你这样做时:
let name1 : string = person.name; //<<<Error here 
你没有给它一个选择。你需要有一个 Union 来反映未定义的类型:
let name1 : string | undefined = person.name; //<<<No error here 
使用您的回答,我能够勾勒出以下内容,基本上是一个接口、一个类和一个对象。我发现这种方法更简单,如果你不介意的话。
// 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());
解决方案 1:删除显式类型定义
由于getPerson已经返回了Person带有名称的 a,因此我们可以使用推断的类型。
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.name可以为空,但name1不能为空。有两种情况:
Person.name 永远不会为空通过使用告诉编译器您确定名称不为空 !
let name1: string = person.name!;
Person.name 可以为空如果名称为空,请指定默认值
let name1: string = person.name ?? "default name";
尝试事先找出实际值。如果person有效name,则将其分配给name1,否则分配undefined。
let name1: string = (person.name) ? person.name : undefined;
小智 5
你可以这样做!
let name1:string = `${person.name}`;
但记住name1可以是空字符串
| 归档时间: | 
 | 
| 查看次数: | 22624 次 | 
| 最近记录: |