Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.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
Typescript 具有联合类型的类型上不存在属性_Typescript - Fatal编程技术网

Typescript 具有联合类型的类型上不存在属性

Typescript 具有联合类型的类型上不存在属性,typescript,Typescript,我有一种类型试图描述一个可序列化的深嵌套“普通javascript”对象: 它允许我定义简单的深嵌套键-值对数字、字符串、布尔值或它们的数组: const thing: MappingReferenceValues = { test: { test2: { test3: "hi", test4: 200, test5: [true, false] } } }; 太好了!声明它很好。它比任何都要好得多,因为它确保了我在那里没有函数,并且

我有一种类型试图描述一个可序列化的深嵌套“普通javascript”对象:

它允许我定义简单的深嵌套键-值对数字、字符串、布尔值或它们的数组:

const thing: MappingReferenceValues = {
  test: {
    test2: {
      test3: "hi",
      test4: 200,
      test5: [true, false]
    }
  }
};
太好了!声明它很好。它比
任何
都要好得多,因为它确保了我在那里没有函数,并且与
未定义的
不同

然而,使用它确实很痛苦:

const output = thing.test.test2.test3
出现一个错误:

Property 'test2' does not exist on type 'string | number | boolean | MappingReferenceValues | string[] | number[] | boolean[] | MappingReferenceValues[]'.
  Property 'test2' does not exist on type 'string'.

test2
不存在于类型字符串上,但它存在于类型
MappingReferenceValues
上。有没有办法避免再次将其强制转换为任何类型?

此错误对您定义的接口有效

如果您收到
MappingReferenceValues
类型的序列化值并对其进行反序列化,您如何知道该类型上存在
test2
嵌套属性

在使用
MappingReferenceValues
作为函数输入参数的示例中更符合逻辑:

函数解析(值:MappingReferenceValues){
值。/*我们不知道键,也不知道点后的类型*/
}
若您需要进一步操作刚刚创建的变量
thing
,则省略类型定义。您仍然可以将其传递给需要
MappingReferenceValues
类型的函数

函数解析(值:MappingReferenceValues){
/*待办事项*/
}
常数事物={
测试:{
测试2:{
测试3:“你好”,
测试4:200,
测试5:[对,错]
}
}
};
const output=thing.test.test2.test3;//工作
解析(事物);//也在工作;

此错误对您定义的接口有效

如果您收到
MappingReferenceValues
类型的序列化值并对其进行反序列化,您如何知道该类型上存在
test2
嵌套属性

在使用
MappingReferenceValues
作为函数输入参数的示例中更符合逻辑:

函数解析(值:MappingReferenceValues){
值。/*我们不知道键,也不知道点后的类型*/
}
若您需要进一步操作刚刚创建的变量
thing
,则省略类型定义。您仍然可以将其传递给需要
MappingReferenceValues
类型的函数

函数解析(值:MappingReferenceValues){
/*待办事项*/
}
常数事物={
测试:{
测试2:{
测试3:“你好”,
测试4:200,
测试5:[对,错]
}
}
};
const output=thing.test.test2.test3;//工作
解析(事物);//也在工作;
您需要区分
thing.test
thing.newTest

根据
MappingReferenceValues
的定义,thing可以包含任何
字符串
键,因此所有这些访问都可以:

let test = thing.test;
let newTest = thing.newTest;
let newTest2 = thing.newTest2; // still 'newTest2' does't not exits on thing.
现在检查
test
newTest
newTest2
的类型。它们都可以是
string | number | boolean | string[]| MappingReferenceValues | number[]| boolean[]| MappingReferenceValues[]

因此,要访问其值,如
test.field
,首先需要将其类型缩小为
MappingReferenceValues

这种变窄可以通过以下方法完成:

function isMappingReferneceValues(a: unknown): a is MappingReferenceValues {
  ...
  return true;
}
您需要区分
thing.test
thing.newTest

根据
MappingReferenceValues
的定义,thing可以包含任何
字符串
键,因此所有这些访问都可以:

let test = thing.test;
let newTest = thing.newTest;
let newTest2 = thing.newTest2; // still 'newTest2' does't not exits on thing.
现在检查
test
newTest
newTest2
的类型。它们都可以是
string | number | boolean | string[]| MappingReferenceValues | number[]| boolean[]| MappingReferenceValues[]

因此,要访问其值,如
test.field
,首先需要将其类型缩小为
MappingReferenceValues

这种变窄可以通过以下方法完成:

function isMappingReferneceValues(a: unknown): a is MappingReferenceValues {
  ...
  return true;
}

这很有趣,因为你会说“你怎么知道它上面有test2嵌套属性?”但我同样会问,我怎么知道它上面有
test
属性?
[key:string]
说明可以有任何字符串属性,但可能没有一个名为
test
,甚至根本没有。这似乎前后矛盾。类似地,它假设它是一个字符串。所以我可以做
事情。test.trim()
,即使它可能是嵌套对象。您定义了根对象上可以有任何名称的键。它可以是
test
或,例如
random
。尝试line
const output=thing.random.test2.test3
,您将得到与
test
属性完全相同的错误。这很有趣,因为您会说“您如何知道它上面有test2嵌套属性?”,但我同样可以问,我如何知道它上面有
test
属性?
[key:string]
说明可以有任何字符串属性,但可能没有一个名为
test
,甚至根本没有。这似乎前后矛盾。类似地,它假设它是一个字符串。所以我可以做
事情。test.trim()
,即使它可能是嵌套对象。您定义了根对象上可以有任何名称的键。它可以是
test
或,例如
random
。尝试line
const output=thing.random.test2.test3
,您将得到与
test
属性完全相同的错误。