当前位置:  开发笔记 > 编程语言 > 正文

从非类继承ES6/TS类

如何解决《从非类继承ES6/TS类》经验,为你挑选了1个好方法。

鉴于该类是从非类扩展(包括但不限于函数),

function Fn() {} 

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

有什么后果?规格对此有何评论?

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

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

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



1> Herrington D..:

TypeScript部分

到目前为止,规范中说clausextends必须后跟TypeReference.和TypeReference必须在形式 A.B.C,像MyModule.MyContainer.所以,从语法上来说,你的代码是正确的.但它不是打字机箱.

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

ES2015 Part

所以,你的问题是普通函数不被识别为TypeScript中的构造函数,这是有争议的,因为ES2015规范只要求对象有一个[[construct]]内部方法.虽然用户定义的函数对象确实拥有它.

ES2015需要BaseClass 是一个构造在运行时.一个对象,isConstructor如果它有[[construct]] 内部的方法.规范说[[construct]]是功能对象的内部方法.用户函数是实例Function Objects,因此它们自然是构造函数.但内置函数和箭头函数可以没有[[construct]].

例如,以下代码将抛出运行时TypeError因为parseInt是内置函数而没有[[construct]]

new parseInt()
// TypeError: parseInt is not a constructor

并从ECMAScript

箭头函数就像内置函数一样缺乏.prototype和任何[[Construct]]内部方法.所以new(()=> {})抛出一个TypeError,否则箭头就像函数一样:

根据经验,没有任何功能prototypenew不可行的.

解决

简而言之,并非每个函数都是构造函数,TypeScript通过要求捕获它new() {}.但是,用户定义的函数是构造函数.

要解决这个问题,最简单的方法是声明Fn为变量,并将其强制转换为构造函数.

interface FnType {}
var Fn: {new(): FnType} = (function() {}) as any

class B extends Fn {}

推理不兼容性

DISCALIMER:我不是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')

另一方面,如果将a ConstructorInterface引入TypeScript并且每个函数都实现了它,则会出现向后不兼容.以下代码现在编译,但不是在ConstructorInterface引入时编译

var a = function (s) {}
a = parseInt // compile error because parseInt is not assignable to constructor

当然,TS团队可以有一个平衡这两个选项的解决方案.但这不是一个高优先级.此外,如果salsa(TS驱动的JavaScript的代号)完全实现.这个问题自然会得到解决.

推荐阅读
惬听风吟jyy_802
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有