任何类型都可以强制转换为Typescript中的数字映射
似乎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 我希望
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
描述其数值属性均具有typestring
的所有对象集
AnyType
是NumberMap
的子类型,因为它的所有数值属性都具有typestring
。(这是非常正确的,因为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好的,我会更新答案。我很乐意帮忙!