打字稿变量?和?

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? 表示变量可以是nullundefinedid! 表示它将被初始化,但不在构造函数中。这应该在 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

这个警告很好,对吧?因为不想误读undefinedtoFixed()方法。您需要先检查 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

【讨论】:

以上是关于打字稿变量?和?的主要内容,如果未能解决你的问题,请参考以下文章

分配前使用的打字稿变量

打字稿中变量之间的区别

访问打字稿类的成员变量是不是需要`this`?

在条件中使用打字稿变量

如何在打字稿中声明全局变量

具有基于变量的标签值的打字稿匿名对象