typescript 打字稿:Type?'string?|?undefined'?is?not?assignable?to?type?'string'

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/54496398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 08:01:33  来源:igfitidea点击:

Typescript: Type?'string?|?undefined'?is?not?assignable?to?type?'string'

typescript

提问by asdasd

When I make any property of an interface optional, I an error like following while assigning its member to some other variable

当我将接口的任何属性设为可选时,在将其成员分配给其他变量时出现如下错误

TS2322: Type?'string?|?undefined'?is?not?assignable?to?type?'string'. ??Type?'undefined'?is?not?assignable?to?type?'string'.

TS2322:类型?'string?|?undefined'?is?not?assignable?to?type?'string'。??Type?'undefined'?is?not?assignable?to?type?'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 

How do I get around this error?

我该如何解决这个错误?

回答by yannick1976

You can now use the non-null assertion operatorthat is here exactly for your use case.

您现在可以使用此处完全适用于您的用例的非空断言运算符

It tells TypeScript that even though something looks like it could be null, it can trust you that it's not:

它告诉 TypeScript,即使某些东西看起来可能为 null,它也可以相信你,它不是:

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

回答by AndreFontaine

To avoid the compilation error I used

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

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

And then validate the empty string.

然后验证空字符串。

回答by Harry

I know this is kinda late answer but another way besides yannick's answer https://stackoverflow.com/a/57062363/6603342to use ! is to cast it as string thus telling TypeScript i am sure this is a string thus converting

我知道这是一个有点晚的答案,但除了 yannick 的答案https://stackoverflow.com/a/57062363/6603342之外的另一种使用方式!是将它转换为字符串从而告诉 TypeScript 我确定这是一个字符串从而转换

let name1:string = person.name;//<<<Error here 

to

let name1:string = person.name as string;

This will make the error go away but if by any chance this is not a stringyou will get a run-time error which is one of the reassons we are using TypeScript to ensure that the type matches and avoid such errors at compile time.

这将使错误消失,但如果有任何机会这不是字符串,您将收到运行时错误,这是我们使用 TypeScript 确保类型匹配并在编译时避免此类错误的原因之一

回答by Lynx 242

try to find out what the actual value is beforehand. If personhas a valid name, assign it to name1, else assign undefined.

尝试事先找出实际值。如果person有一个有效的name,将其分配给name1,否则分配undefined

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

回答by igo

As of TypeScript 3.7 you can use nullish coalescing operator??. You can think of this feature as a way to “fall back” to a default value when dealing with null or undefined

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

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

The ??operator can replace uses of ||when trying to use a default value and can be used when dealing with booleans, numbers, etc. where ||cannot be used.

??操作可替代的用途||尝试使用默认值,并且可以与布尔值,数字等,其中处理时,可以使用时,||不能使用。

回答by Dmitry Lobov

You trying to set variable name1, witch type set as strict string (it MUST be string) with value from object field name, witch value type set as optional string (it can be string or undefined, because of question sign). If you really need this behavior, you have to change type of name1like this:

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

let name1: string | undefined = person.name;

And it'll be ok;

一切都会好的;

回答by Konkret

Here's a quick way to get what is happening:

这是了解正在发生的事情的快速方法:

When you did the following:

当您执行以下操作时:

name? : string

姓名?: 细绳

You were saying to TypeScript it was optional. Nevertheless, when you did:

你对 TypeScript 说它是可选的。然而,当你这样做时:

let name1 : string = person.name; //<<<Error here 

You did not leave it a choice. You needed to have a Union on it reflecting the undefined type:

你没有给它一个选择。你需要有一个 Union 来反映未定义的类型:

let name1 : string | undefined = person.name; //<<<No error here 

Using your answer, I was able to sketch out the following which is basically, an Interface, a Class and an Object. I find this approach simpler, never mind if you don't.

使用您的回答,我能够勾勒出以下内容,基本上是一个接口、一个类和一个对象。我发现这种方法更简单,如果你不介意的话。

// 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());

回答by Nick Bull

Note that if the variable is from an array or destructuring, you can provide default values:

请注意,如果变量来自数组或解构,您可以提供默认值:

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);

回答by Karol Majewski

Solution 1: Remove the explicit type definition

解决方案 1:删除显式类型定义

Since getPersonalready returns a Personwith a name, we can use the inferred type.

由于getPerson已经返回Person带有名称的 a,我们可以使用推断类型。

function getPerson(){
  let person = {name:"John"};
  return person;
}

let person = getPerson();

If we were to define person: Personwe would lose a piece of information. We know getPersonreturns an object with a non-optional property called name, but describing it as Personwould bring the optionality back.

如果我们要定义,person: Person我们将丢失一条信息。我们知道getPerson返回一个具有非可选属性的对象,称为name,但将其描述为Person会带回可选性。

Solution 2: Use a more precise definition

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

Solution 3: Redesign your interface

解决方案 3:重新设计您的界面

A shape in which all properties are optional is called a weak typeand usually is an indicator of bad design. If we were to make namea required property, your problem goes away.

所有属性都是可选的形状称为弱类型,通常是不良设计的指标。如果我们要制作name必需的属性,那么您的问题就会迎刃而解。

interface Person {
  name:string,
  age?:string,
  gender?:string,
  occupation?:string,
}

回答by Michael Obasi

You could make use of Typescript's optional chaining. Example:

您可以使用 Typescript 的可选链接。例子:

const name = person?.name;

If the property nameexists on the personobject you would get its value but if not it would automatically return undefined.

如果该属性name存在于person对象上,您将获得它的值,但如果不存在,它将自动返回 undefined。

You could make use of this resource for a better understanding.

您可以利用此资源来更好地理解。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html