typescript - Object 和 {} 类型有什么区别,什么时候用哪个
问题描述
他们非常清楚他们的目的是什么。但这并不能满足作为程序员的我。对我来说(我刚开始学习 Type Script,所以这可能是错误的),他们可以也不能做几乎相同的事情。除了你可以实现 Object(仍然怀疑为什么有人需要这样做)但你不能实现 {}。(当然,您也可以只使用 new Object 或调用 Object.keys 之类的东西。但这在这里无关紧要)。
所以对于要编写 TypeScipt 代码的人来说。类型 Object 和 {} 有什么区别。为什么类型 {} 甚至存在?
解决方案
你不能实现 {}
这是不正确的。这是允许的:
type Empty = {};
class B implements Empty {
}
诚然,它没有多大意义——implements Empty
不会为 的用户添加任何信息,B
也不会对实现添加任何约束。
为什么类型 {} 甚至存在?
如果你对名为“intersection”和“union”的类型进行操作,你迟早会想要一个类型X
,对于任何类型T
,满足等价T | X = T
和T & X = X
。这X
是{}
一种被定义为不具有任何属性的类型。它为什么存在?出于同样的原因,存在一个空集。它在哪里有用?当您需要一个具体类型但不确切知道它可能具有哪些属性时,可以在任何地方使用。这是一个例子:
type BaseEventHandlers<Event extends string> = { [event in Event]: {} };
// in BaseEventHandlers we don't know exact type of data that comes with different event types,
// so we have it as {}
// it's better than any because any can have unpredictable effect on type checking
// it's better than Object because Object has properties with names
// that could possibly interfere with our data
type EventHandlers<H extends BaseEventHandlers<string>> = { [event in keyof H]: (args: H[event]) => void };
// here we can express a constraint that each event handler
// must receive an object of appropriate type
// example
type UserEvents = {
user_added: { name: string };
user_joined_team: { userName: string, teamName: string };
}
const userHandlers: EventHandlers<UserEvents> = {
// what is checked by the compiler here:
// all events have handlers assigned
// each handler has correct names for arguments
// argument types are inferred from types in `UserEvents`
// and do not need to be repeated here
user_added: ({ name }) => {
},
user_joined_team: ({ userName, teamName }) => {
}
}
更新
糟糕,事实证明{}
,以及任何像 的原始类型string
,仍然被隐式地认为具有Object
- 的所有预定义属性,正如 J.Doe 所指出的那样,这没有错误:
const userHandlers: EventHandlers<UserEvents> = {
// what is checked by the compiler here:
// all events have handlers assigned
// each handler has correct names for arguments
// argument types are inferred from types in `UserEvents`
// and do not need to be repeated here
user_added: ({ name, toString }) => {
所以我的回答只是一厢情愿——这就是我想要的,但实际上和{}
之间几乎没有区别。它们仍然不同:{}
Object
type o = keyof Object; // 'constructor' | 'toString' | ...
type e = keyof {}; // never
但差异是微妙的,我不确定如何在实践中使用它。就个人而言,我更喜欢用{}
不带任何属性的类型来表示,Object
当我需要参考Object
Javascript 运行时提供的原型时。string
因此,差异主要是名义上的,与和String
之间的差异几乎相同。
推荐阅读
- java - 从其他设备运行时java邮件程序不起作用
- html - div元素中的footer元素和header元素会成为div元素的header和footer吗?
- xamarin - 有没有办法可以在我的 C# 代码中访问静态资源?
- angular - ngrx 不保持状态
- css - 在 FabricJS 中翻译视口时边界对象错误,用户单击对象时无法选择对象
- r - R中的许多热门编码器
- java - ByteBuffer 内存分配
- adal - 从 Azure AD Passport BearerStrategy 的 cookie 中检索 access_token
- angular - 2个模块的角度动态组件声明
- javascript - 替代 CSV 数组转换以更快地获取数据