【问题标题】:Why can't Data, which extends {}, be assigned to {}? Does {} != {}?为什么不能将扩展 {} 的 Data 分配给 {}? {} != {} 吗?
【发布时间】:2021-12-02 06:09:57
【问题描述】:

我不明白为什么这段代码会出错。有人可以帮助我吗?我环顾四周,发现了很多关于堆栈溢出的例子,但我不明白最基本的问题。为什么不能将扩展 {} 的 Data 分配给 {}? {} != {} 吗?

function fn<Data extends {}>(data: Data = {}) { }
//                          ^^^^^^^^^^^^^^^^^
//                    Type '{}' is not assignable to type 'Data'.

类型“{}”不可分配给类型“数据”。 “{}”可分配给“Data”类型的约束,但“Data”可以用约束“{}”的不同子类型实例化。ts(2322)

【问题讨论】:

  • 你为什么要扩展{}
  • 我希望这个函数的用户能够传入任何对象。基本上,它应该防止传入原始值。
  • @JacobWeisenburger 好的。后续问题。为什么需要data 有默认值?
  • 不完全是您的要求,但是是的,{} != {}
  • @Olian04 因为如果没有传递任何值,我希望 data 是一个空对象而不是 undefined。

标签: typescript


【解决方案1】:

因为Data 的类型可能需要{} 中不存在的属性。

比如说,你创建了如下界面:

interface FooData {
  foo: string
}

我们知道我们不能这样做:

const data: FooData = {};
//                    ^^ - missing required property `foo: string`

当您将默认值设置为{} 时,这正是您在fn 声明中所尝试的。用 TypeScript 的话来说:

“{}”可分配给“Data”类型的约束,但“Data”可以用约束“{}”的不同子类型来实例化。

在这种情况下,FooData“约束'{}'的不同子类型”,它需要foo 属性,而{} 上不存在该属性。 {} 不保证传递给Data 的类型参数将被{} 满足,因此不允许将{} 作为默认值。


另外,您可能打算改为扩展类型 Record&lt;string, any&gt;{}the empty type 通常不是您想要的(参见 here),因为它允许除 nullundefined 之外的所有内容。

注意:在大多数情况下,为泛型类型的参数定义默认值是不可行的,因为实际类型可能比默认值更具体(如上所述)。

【讨论】:

  • 我希望这个函数的用户能够传入任何对象。基本上,它应该防止传入原始值。有没有不同的方法来允许任何对象而不允许原始值?
  • @JacobWeisenburger 你需要使用泛型吗?否则只需 data: Object = {} 就足够了。
猜你喜欢
  • 2019-03-07
  • 2012-06-13
  • 2020-05-25
  • 2017-07-20
  • 2012-11-10
  • 1970-01-01
  • 2016-12-22
相关资源
最近更新 更多