打字稿变量?和?
Posted
技术标签:
【中文标题】打字稿变量?和?【英文标题】:Typescript variables with ? and? 【发布时间】:2021-11-29 06:21:06 【问题描述】:当我在 typescript 中声明一个变量时,如下所示:
id: number
我收到以下错误:
Property 'id' has no initializer and is not definitely assigned in the constructor.ts(2564)
如果我将变量更改为以下之一,错误就会消失:
id?: number
id!: number
这些有什么区别,我应该在什么情况下使用上面的?
【问题讨论】:
id?
表示变量可以是null
或undefined
,id!
表示它将被初始化,但不在构造函数中。这应该在 Typescript 文档中解释
@UnholySheep id?
不包括域中的null
而且您不能将?
与局部变量(“变量”)一起使用,只能使用属性和参数。
@jcalz 啊,我的错 - 我错误地认为它包含与非空断言运算符相同的类型
@wonderfulworld 我真诚地怀疑这不是重复的。
【参考方案1】:
当你写这个时:
class Optional
id?: number;
您已声明id
是optional property。这意味着它可能存在也可能不存在于Optional
的实例中。如果存在,则该值应该是number
(或者可能是undefined
,除非您使用的是the --exactOptionalPropertyTypes
compiler option)。如果它不存在,那么如果您读取id
属性,则该值将是undefined
。
以上解决了编译器警告,因为您不需要初始化可选属性;当你读到它时,它就是undefined
。
无论如何,这意味着您不能只将id
属性用作number
:
const o = new Optional();
o.id.toFixed(2) // compiler error!
//~~ <-- Object is possibly undefined
这个警告很好,对吧?因为不想误读undefined
的toFixed()
方法。您需要先检查 undefined
,可能使用optional chaining operator (?.
):
o.id?.toFixed(2) // okay
当您不确定属性是否会在用户想要访问它们的时间分配,并且您希望保护这些用户免受潜在的运行时错误时,可选属性是一种合理的方法。
另一方面,当你写这个时:
class Asserted
id!: number
您已断言id
属性has definitely been assigned。这个断言是你告诉编译器一些它不能自己验证的东西。这在您实际分配属性但编译器无法遵循逻辑的情况下很有用:
class ActuallyAssigned
id!: number
constructor()
Object.assign(this, id: 123 );
ActuallyAssigned
的实例将在构造函数中设置id
属性,因为the Object.assign()
function 将属性从所有后续参数复制到第一个参数中。但是编译器无法理解这一点,因此如果没有明确的赋值断言,您会收到警告。在这里消除该警告是合理的。
但在上面的Asserted
中,这是不合理的。你对编译器撒了谎。它看不到id
已分配,因为它实际上未 已分配。因此,如果您继续将id
属性视为number
,即使它可能是undefined
,您也不会收到编译器警告:
a.id.toFixed(2) // no compiler error, but
// ? RUNTIME ERROR: o.id is undefined
因此,当用户想要访问属性很可能是undefined
时,不建议使用明确的赋值断言。
Playground link to code
【讨论】:
以上是关于打字稿变量?和?的主要内容,如果未能解决你的问题,请参考以下文章