Record<string, any> 和 {} 之间的区别?

max*_*son 2 javascript types typescript

我看到的唯一区别是{}您不能向Record<string, any>. 还有什么我想念的吗?

示例代码(游乐场链接):

const one: Record<string, any> = { foo: 1 }
one.bar = 2

const two: {} = { foo: 1 }
two.bar = 2 // Property 'bar' does not exist on type '{}'.(2339)
Run Code Online (Sandbox Code Playgroud)

Jer*_*eBu 6

类型{}只匹配一个空对象。

Record<string, any> 将类似于 { [key: string]: any}

更新:我的第一句话是错误的。该类型{}几乎与接受的答案中所说的相匹配


Mac*_*ora 6

好的,真正的问题是为什么我们可以将任何对象分配到{}. 这更多是关于语言设计选择的。语言建立在结构子类型兼容性之上。

TypeScript 中的类型兼容性基于结构子类型。结构类型是一种仅基于其成员关联类型的方法。这与名义打字相反。

这意味着我们可以为其子类型分配更松散的类型值。在您的代码中{}是最宽的对象类型,我们可以说它是每个对象类型的父类型,换句话说,每个其他对象类型都是{}. 下面是一些示例检查:

type ISubTypeOfEmptyObj<T> = T extends {} ? true : false
type Check1 = ISubTypeOfEmptyObj<{bar: 2}> // yes it is
type Check2 = ISubTypeOfEmptyObj<{foo: 2, bar: 'a'}> // yes it is
type Check3 = ISubTypeOfEmptyObj<number> // surprisingly that is also true
const a: {} = 1; // no error 
Run Code Online (Sandbox Code Playgroud)

它证明了什么 - 您{}几乎可以凭空创建实例的事实(只有nullundefined值不能是 的成员{})。但同样正确的是,在初始化之后,您不能只将某些属性设置为这样的值,因为类型说没有。换句话说,你{}几乎可以用任何东西来制作,但你只能像空物体一样使用它。

Record<string, any>是比 更严格的类型{},例如,每个数组类型都可以分配给{},不能分配给Record<string, any>,对于其他类型(如stringor )也是如此numberRecord<string, any>表示具有任何字符串属性的所有对象,因此您可以将任何字符串属性附加到对象,因为类型将成立。