任何类型都可以强制转换为Typescript中的数字映射

任何类型都可以强制转换为Typescript中的数字映射,typescript,Typescript,似乎typescript允许使用类型为number的键将任何类型强制转换为映射。下面是一个示例代码: type NumberMap = { [key: number]: string } type AnyType = { foo: string bar: boolean[] } const anyTypeObj: AnyType = { foo: "foo", bar: [false] } const numberMap: NumberMap = anyTypeObj 我希望

似乎typescript允许使用类型为
number
的键将任何类型强制转换为映射。下面是一个示例代码:

type NumberMap = {
  [key: number]: string
}

type AnyType = {
  foo: string
  bar: boolean[]
}

const anyTypeObj: AnyType = { foo: "foo", bar: [false] }

const numberMap: NumberMap = anyTypeObj
我希望在尝试将
AnyType
分配给
NumberMap
时,最后一行会给我一个类型错误,但它没有。但是,将对象文字直接指定给
NumberMap
类型的变量会按预期工作,并导致类型错误:

const numberMap: NumberMap = { foo: "foo", bar: [false] }
下面是一个在typescript上使用上述代码的示例

为什么typescript允许将任何类型的对象强制转换为
NumberMap

类型
{[key:number]:string}
是否有什么特殊之处使其具有这种行为

Typescript在将对象文字指定给变量时执行一些额外的检查。这就是所谓的。其思想是,分配给类型不具有完全相同属性的变量的对象文字很可能是错误的。另一方面,在Javascript中,不完全匹配的重分配和参数值很常见,因此当右侧表达式不是对象文字时,只要值的类型与变量的类型兼容,就允许不精确的赋值

在您的示例中,
anyTypeObj
NumberMap
兼容。您可以将
anyTypeObj
视为空的
NumberMap
NumberMap
的约定指定,如果通过数字键访问属性,结果将是字符串
anyTypeObj
没有数字键,因此在任何情况下都不会出现这种情况

请注意,一旦将
anyTypeObj
分配给
numberMap
,您就不能通过
numberMap
访问
foo
bar
属性,因为
numberMap
类型没有声明这些属性

编辑:margaretkru接着问了这个问题:

为什么
{[key:number]:string}
不强制要求对象上的所有键必须是
number
类型和值
string
?因为
anyTypeObj
具有带有
string
键的属性,所以在这种情况下,我希望cast将
NumberMap
失败

我的解释是,变量可以接受任何类型为该变量类型的值。我从子类型的角度考虑兼容性。例如:

const a: Animal = new Cow()
如果
Cow
Animal
的一个子类,即使
Cow
具有
Animal
不具有的属性,该方法仍然有效

在面向对象语言中,类型是类或接口,如果
B
显式扩展或实现
a
,则类型
B
仅被视为
a
的子类型。但有些语言(包括Typescript)的观点更为笼统。“类型”最一般的定义是对满足特定标准的一组可能值的描述
B
a
的一个子类型,前提是
B
描述了一组值,该值是
a
描述的值集的子集。无论
B
是否在其定义中命名
A

NumberMap
描述其数值属性均具有type
string
的所有对象集


AnyType
NumberMap
的子类型,因为它的所有数值属性都具有type
string
。(这是非常正确的,因为
AnyType
没有数字属性)。
AnyType
上的字符串属性会干扰
NumberMap
的合同,因为
NumberMap
没有说明任何字符串属性。

正确,谢谢。我读了很多次文档,但仍然没有注意到它,这就解释了我的部分问题。但是为什么
{[key:number]:string}
不强制要求对象上的所有键都必须是
number
类型和值
string
?因为
anyTypeObj
具有带有
string
键的属性,所以我希望在这种情况下,cast将
NumberMap
失败。变量接受任何类型与变量类型相同的值。我从子类型的角度考虑兼容性。这是有效的:
const a:Animal=new Cow()
如果
Cow
Animal
的子类,即使
Cow
具有
Animal
没有的属性。在类型脚本中,子类型不必是子类
AnyType
NumberMap
的子类型,因为它的所有数值属性都具有
string
类型(因为它没有数值属性,所以非常正确)。额外的道具不会干扰NumberMap的合同。哦,现在我终于明白了:)谢谢你的解释!我想你最后的评论可以包含在答案中,它为我澄清了一些事情。@margaretkru好的,我会更新答案。我很乐意帮忙!