当我作出接口可选的任何属性,我喜欢而分配其成员的一些其它可变以下的错误
TS2322:键入“字符串” |未定义''不能分配给``字符串''类型。类型'undefined'不能分配给类型'string'。
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
如何解决此错误?
答案 0 :(得分:24)
从TypeScript 3.7开始,您可以使用无效合并运算符 ??
。您可以认为此功能是在处理null或未定义时将其“回退”到默认值的一种方法
let name1:string = person.name ?? '';
在尝试使用默认值时,??
运算符可以替换||
的使用,并且在不能使用||
的布尔值,数字等情况下也可以使用。 / p>
从TypeScript 4开始,您可以将??=
赋值运算符用作a ??= b
,这是a = a ?? b;
的替代选择
答案 1 :(得分:5)
一种更易于生产的方式来处理此问题,实际上是确保存在name
。假设这只是一群人参与的较大项目的最小示例,那么您不知道getPerson
将来会如何变化。
if (!person.name) {
throw new Error("Unexpected error: Missing name");
}
let name1: string = person.name;
或者,您可以将name1
键入为string | undefined
,并进一步处理undefined
的情况。但是,通常最好尽早处理意外错误。
您还可以通过省略显式类型来让TypeScript推断类型:let name1 = person.name
仍将防止例如name1
被重新分配为数字。
答案 2 :(得分:4)
为避免我使用的编译错误
let name1:string = person.name || '';
然后验证空字符串。
答案 3 :(得分:3)
根据您的定义,Person.name
可以为空,但 name1
不能。
有两种情况:
Person.name
永远不会为空使用 !
let name1: string = person.name!;
Person.name
可以为空如果名称为空,请指定默认值
let name1: string = person.name ?? "default name";
答案 4 :(得分:2)
试图找出实际值提前是什么。如果person
具有有效的name
,请将其分配给name1
,否则分配undefined
。
let name1: string = (person.name) ? person.name : undefined;
答案 5 :(得分:2)
我知道这是一个较晚的答案,但除了yannick的答案https://stackoverflow.com/a/57062363/6603342之外,还有另一种使用方式!是将其转换为字符串,从而告诉TypeScript我确定这是字符串,因此可以转换
let name1:string = person.name;//<<<Error here
到
let name1:string = person.name as string;
这将使错误消失,但是如果有可能是不是字符串,您将收到运行时错误,这是我们使用TypeScript来确保类型正确的原因之一匹配并避免在编译时出现此类错误。
答案 6 :(得分:2)
如果您从 <Person>
函数中删除 getPerson
转换,那么 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!;
答案 7 :(得分:2)
如果您想拥有可为空属性,请将您的界面更改为:
interface Person {
name?:string | null,
age?:string | null,
gender?:string | null,
occupation?:string | null,
}
如果不是未定义,您可以删除属性名称前面的问号 (?)。
答案 8 :(得分:1)
你可以这样做!
let name1:string = `${person.name}`;
但记住 name1
可以是空字符串
答案 9 :(得分:1)
您现在可以使用完全适合您的用例的non null assertion operator。
它告诉打字稿,即使某些东西看起来可能为空,也可以相信它不是:
let name1:string = person.name!;
// ^ note the exclamation mark here
答案 10 :(得分:1)
您尝试设置变量name1
,将女巫类型设置为严格字符串(必须为字符串),对象字段为name
,女巫值类型设置为可选字符串(可以为string或未定义,因为有问号)。如果您确实需要这种行为,则必须像这样更改name1
的类型:
let name1: string | undefined = person.name;
没关系;
答案 11 :(得分:0)
解决方案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,
}
答案 12 :(得分:0)
您可以使用NonNullable
实用程序类型:
示例
type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]
Docs。
答案 13 :(得分:0)
您可以使用Typescript的可选链接。 示例:
const name = person?.name;
如果name
对象上存在属性person
,则将获得其值,但如果不存在,它将自动返回undefined。
您可以利用此资源更好地理解。
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html
答案 14 :(得分:0)
这是了解正在发生的事情的快速方法:
执行以下操作时:
名字? :字符串
您对TypeScript说这是可选的。不过,当您这样做时:
let name1 : string = person.name; //<<<Error here
您没有选择。您需要在其上包含一个反映未定义类型的联合体:
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());
答案 15 :(得分:-1)
请注意,如果变量来自数组或解构,则可以提供默认值:
const { DB_HOST = "localhost", DB_PORT: "5432" } = process.env
db.connect(DB_HOST, DB_PORT);
const connectToDb = (host = "localhost", port: "5432") => db.connect(host, port);
答案 16 :(得分:-8)
有同样的问题。
我发现react-scrip将"strict": true
添加到tsconfig.json
。
删除后,一切正常。