typescript - 构造函数接口:没有匹配构造函数的类仍然是可赋值的
问题描述
想象一下,我们有一个接口,它定义了构造函数应该接受哪些参数:
interface Ctr {
new (num: number): any;
}
然后我们有一个带有默认构造函数的类:
class DefCtr {
}
然后,出于某种原因,我可以将DefCtr
class 分配给 type 的变量Ctr
:
const Instance: Ctr = DefCtr;
const i = new Instance(1);
console.log(i);
// The output is:
// DefCtr {}
所以Instance
是一个DefCtr
类(它没有构造函数接受数字)。但是界面迫使我在创建它的实例时传递一个数字(将被忽略)。
有趣的是,这仅在类具有默认构造函数时才有效。例如,这不起作用:
interface Ctr {
new (num: number): any;
}
class NotDefCtr {
// Lets create a non-default constructor
constructor(str: string) {
}
}
const Instance: Ctr = NotDefCtr; // Error:
// Type 'typeof NotDefCtr' is not assignable to type 'Ctr'.
// Types of parameters 'str' and 'num' are incompatible.
// Type 'number' is not assignable to type 'string'.
错误是有道理的。但从我的角度来看,尝试使用默认构造函数分配一个类时收到错误也是有意义的(因为它没有任何其他构造函数匹配接口)。
解决方案
TypeScript FAQ 有一个条目:为什么参数较少的函数可以分配给参数较多的函数?. 除了使用 newable 而不是 callable 之外,这是同样的问题。我将把该条目翻译成这种情况:
这是预期和期望的行为。有一个可替代性原则说,如果一个对象X
可以用来代替某个对象Y
,那么X
它就是 的子类型或可分配给Y
。
在这种情况下,DefCtr
是 的子类型,Ctr
因为DefCtr
的构造函数可以安全地忽略额外number
参数。ButNotDefCtr
不是的子类型,Ctr
因为NotDefCtr
的类型表明它需要一个类型的参数string
;anumber
不能安全地用作 a string
,因此它不兼容。
(旁白:事实证明NotDefCtr
' 的构造函数实际上忽略了它的输入,所以在运行时不会发生爆炸。但是类型系统并不关心构造函数的特定实现;它看到一个合同的签名说NotDefCtr
' 的构造函数是在它的权利范围内期望一个类型的参数string
。所以用 替换 a 仍然是一个错误Ctr
。NotDefCtr
)
好的,希望有帮助;祝你好运!
推荐阅读
- ruby-on-rails - 创建表单(Simpleform)PG :: NotNullViolation:错误:Rails列中的空值
- sql-server - SQL Server 中具有可重复读取隔离级别的并发读取和更新事务
- php - 如何使用 tcPdf 添加自定义 html 标签?
- crc - 我应该如何为 HDLC 实施 CRC?(CRC16-CCITT)
- javascript - 无法为 Material UI 中的选项卡应用水平滚动
- reactjs - 如何访问 mapstatetoprops 方法中的本地状态
- angular - 分配一个方法来动态点击
- api-platform.com - API Platform GraphQL 为相关实体创建具有实体特定连接的通用类型 IterableConnection
- javascript - Axios/Express 之间的数据丢失
- javascript - TypeError:Undefined is not an object 在 ReactNative 中尝试动画时