鉴于该类是从非类扩展而来的(包括但不限于功能),
function Fn() {}
class Class extends Fn {
constructor() {
super();
}
}
有什么后果?规格说明了什么?
看起来Babel,Google V8和Mozilla Spidermonkey的当前实现都可以,并且TypeScript抛出
类型'()=> void'不是构造函数类型
如果这是有效的ES2015代码,那么在TypeScript中处理它的正确方法是什么?
到目前为止,该规范说extends
必须在子句之后加上TypeReference。并且TypeReference必须采用的形式A.B.C<TypeArgument>
,例如MyModule.MyContainer<MyItem>
。因此,从语法上讲,您的代码是正确的。但这不是打字的情况。
规范说BaseClass
必须是有效的打字稿类。然而,该规范已经过时,因为说这里。现在,TypeScript允许在extends子句中使用表达式,只要将表达式计算为构造函数即可。好的定义是基于实现的。你可以在这里看到它。简而言之,如果表达式实现new() {}
接口,则可以将其视为构造函数。
因此,您的问题是普通函数在TypeScript中未被识别为构造函数,这是有争议的,因为ES2015规范仅要求对象具有[[construct]]
内部方法。用户定义的函数对象确实具有它。
ES2015要求在运行时提供BaseClass
一个构造函数。一个对象,如果它具有内部方法。规范说是Function Object的内部方法。用户函数是的实例,因此它们自然是构造函数。但是内置函数和箭头函数不能有。isConstructor
[[construct]]
[[construct]]
Function Objects
[[construct]]
例如,以下代码将抛出运行时,TypeError
因为parseInt
它是内置函数,并且没有[[construct]]
new parseInt()
// TypeError: parseInt is not a constructor
从ECMAScript
箭头函数就像内置函数一样,它们都缺少.prototype和任何[[Construct]]内部方法。因此,新的(()=> {})会引发TypeError,但是箭头类似于函数:
根据经验,没有的任何功能prototype
都是new
不可行的。
简而言之,并不是每个函数都是构造函数,TypeScript通过require来捕获它new() {}
。但是,用户定义的函数是构造函数。
要解决此问题,最简单的方法是将其声明Fn
为变量,然后将其强制转换为构造函数。
interface FnType {}
var Fn: {new(): FnType} = (function() {}) as any
class B extends Fn {}
免责声明:我不是TypeScript的核心贡献者,而是只有TS迷,他有几个与TS相关的项目。所以这部分是我个人的猜测。
TypeScript是一个始于2012年的项目,当时ES2015仍在昏暗的黑暗中若隐若现。TypeScript对于类语义没有很好的参考。
那时,TypeScript的主要目标是保持与ES3 / 5的兼容性。因此,new
在TypeScript中使用函数是合法的,因为在ES3 / 5中它也是合法的。同时,TypeScript还旨在捕获编程错误。extends
一个函数可能是一个错误,因为该函数可能不是明智的构造函数(例如,仅出于副作用的函数)。extends
在ES3 / 5中甚至不存在!因此,TypeScript可以自由定义其自己的用法extends
,从而extends
必须与class
变量配对。这使TypeScript更具TypeSafe,同时与JavaScript兼容。
现在,ES2015规格已完成。JavaScript也有一个extends
关键字!然后出现不兼容性。正在努力解决不兼容问题。但是,仍然存在问题。如上所述,由于内置函数,所以不能扩展类型() => void
或Function
类型。以下代码将中断
var a: (x: string) => void = eval
new a('booom')
另一方面,如果将aConstructorInterface
引入TypeScript中,并且每个函数文字都实现了它,则将出现向后不兼容的情况。下面的代码现在可以编译,但不能在何时ConstructorInterface
引入
var a = function (s) {}
a = parseInt // compile error because parseInt is not assignable to constructor
当然,TS团队可以有一个平衡这两种选择的解决方案。但这不是一个高度优先事项。另外,如果完全实现了salsa,即TS驱动的JavaScript的代号。这个问题自然会解决。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句