Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/465.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript TypeScript:访问对象上未定义的键时返回的类型错误?_Javascript_Typescript_Types - Fatal编程技术网

Javascript TypeScript:访问对象上未定义的键时返回的类型错误?

Javascript TypeScript:访问对象上未定义的键时返回的类型错误?,javascript,typescript,types,Javascript,Typescript,Types,在TypeScript中使用带有可变键的对象时,我注意到了意外的类型 给定以下代码 类型MyType={ [x:编号]:编号 } 常数o:MyType={ 0: 1, } 常数a=o[0];//返回类型正确标识为数字 常数b=o[1];//返回类型应该是未定义的,编译器不允许这样做 我注意到,当使用变量键的[x:number]语法定义对象类型时,使用[…]的对象访问类型无法正确检测 VSCode向我显示a和b都有类型number。类型不应该是number | undefined,因为键可能未定

在TypeScript中使用带有可变键的对象时,我注意到了意外的类型

给定以下代码

类型MyType={
[x:编号]:编号
}
常数o:MyType={
0: 1,
}
常数a=o[0];//返回类型正确标识为数字
常数b=o[1];//返回类型应该是未定义的,编译器不允许这样做
我注意到,当使用变量键的
[x:number]
语法定义对象类型时,使用
[…]
的对象访问类型无法正确检测

VSCode向我显示
a
b
都有类型
number
。类型不应该是
number | undefined
,因为键可能未定义?将
a
b
记录到控制台时,
a
编号
,而
b
未定义的

如果将类型为
MyType
的对象传递给函数,并且该函数访问该对象中的键,然后执行如下操作,则问题会变得更严重:

函数乐趣(o:MyType):编号{
返回o[10000]?null//在运行时可以是数字或null
}
没有显示错误。但是当代码运行时,
o[10000]
未定义,因此返回值为
null
,这不是一个有效的数字。想象一下,使用此返回值执行进一步的计算,这些计算都基于假设是有效数字。这将导致编译器本应检测到的运行时错误(如果我不理解完全错误的内容,我是TS新手)

(这些示例中使用的TypeScript由CreateReact应用程序配置,我没有更改任何设置)

类型不应该改为number | undefined吗?因为键可能未定义

如果你愿意,你可以选择;只需将其定义为:

type MyType = {
  [x: number] : number | undefined
}
如果您希望访问可能不存在的随机属性,这可能很有用

但另一方面,以更严格的方式使用对象是相当常见的,这样可以避免访问不存在的属性。例如,如果您编写的代码通常使用
Object.keys(o)
作为。。。在
中,为了决定要访问哪些属性,您已经在做一些工作来确保它的存在,而typescript总是告诉您它可能未定义,这可能会让您感到沮丧

类型不应该改为number | undefined吗?因为键可能未定义

如果你愿意,你可以选择;只需将其定义为:

type MyType = {
  [x: number] : number | undefined
}
如果您希望访问可能不存在的随机属性,这可能很有用


但另一方面,以更严格的方式使用对象是相当常见的,这样可以避免访问不存在的属性。例如,如果您编写的代码通常使用
Object.keys(o)
作为。。。在
中,为了确定要访问哪些属性,您已经在做确保它存在的工作,而且typescript总是告诉您它可能未定义,这可能会让您感到沮丧。

您的
MyType
定义了一个索引访问器,允许任何数字用作对象的访问器:

type MyType = {
  [x: number] : number
}
这意味着,就类型安全而言,任何数字都可以使用索引访问器访问对象,类似于数组

您的对象只定义一个属性,但类型检查器(编译时间)没有查看您的对象,它是在运行时创建的。类型检查器只知道
MyType
,任何数字都是有效值,可用于索引类型为或扩展
MyType
的任何对象

您必须记住,在运行时,您的对象仍然只是一个常规的旧JavaScript对象,并且一旦编译并运行代码,TypeScript就不再适用

如果要定义具有一定数量属性的类型,则应使用一定数量的属性构造类型,而不是使用索引访问器:

interface MyType {
  0: number
}

const o: MyType = { 0: 1 } // valid
const o2: MyType = { 1: 1 } // type checking error
o[0] // valid
o[1] // type checking error 

您的
MyType
定义了一个索引访问器,允许任何数字用作对象的访问器:

type MyType = {
  [x: number] : number
}
这意味着,就类型安全而言,任何数字都可以使用索引访问器访问对象,类似于数组

您的对象只定义一个属性,但类型检查器(编译时间)没有查看您的对象,它是在运行时创建的。类型检查器只知道
MyType
,任何数字都是有效值,可用于索引类型为或扩展
MyType
的任何对象

您必须记住,在运行时,您的对象仍然只是一个常规的旧JavaScript对象,并且一旦编译并运行代码,TypeScript就不再适用

如果要定义具有一定数量属性的类型,则应使用一定数量的属性构造类型,而不是使用索引访问器:

interface MyType {
  0: number
}

const o: MyType = { 0: 1 } // valid
const o2: MyType = { 1: 1 } // type checking error
o[0] // valid
o[1] // type checking error 

如果有人想要对此问题的“官方”答案,请参阅,请求在索引签名值域中自动包含
未定义的
,以及来自TS团队领导的关于为什么他们认为这不是一个好主意的评论(和)(这会被频繁使用,以至于实际上不会提供安全性)谢谢你的链接。我阅读了大多数评论,我仍然认为默认类型应该包括
未定义的
。主要原因是您可能忘记自己添加
未定义的
。此外,您不希望在
forEach
条目中有
|未定义的
,因为在这种情况下,您知道它不是未定义的。在github问题上,大多数人似乎都同意我的观点。令人遗憾的是,TS团队不想改变这一点,因为这是导致许多运行时错误和类型错误的原因