从非类继承ES6 / TS类

那将是烧瓶

鉴于该类是从非类扩展而来的(包括但不限于功能),

function Fn() {} 

class Class extends Fn {
    constructor() {
        super();
    }
}

有什么后果?规格说明了什么?

看起来Babel,Google V8和Mozilla Spidermonkey的当前实现都可以,并且TypeScript抛出

类型'()=> void'不是构造函数类型

如果这是有效的ES2015代码,那么在TypeScript中处理它的正确方法是什么?

赫灵顿·暗霍尔姆

TypeScript零件

到目前为止,该规范extends必须在子句之后加上TypeReference并且TypeReference必须采用的形式A.B.C<TypeArgument>,例如MyModule.MyContainer<MyItem>因此,从语法上讲,您的代码是正确的。但这不是打字的情况。

规范说BaseClass必须是有效的打字稿类。然而,该规范已经过时,因为说这里现在,TypeScript允许在extends子句中使用表达式,只要将表达式计算为构造函数即可。好的定义是基于实现的。你可以在这里看到它简而言之,如果表达式实现new() {}接口,则可以将其视为构造函数

ES2015部分

因此,您的问题是普通函数在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关键字!然后出现不兼容性。正在努力解决不兼容问题。但是,仍然存在问题。如上所述,由于内置函数,所以不能扩展类型() => voidFunction类型以下代码将中断

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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章