javascript – 從非類繼承ES6 / TS類
給定類從非類擴充套件(包括但不限於函式),
function Fn() {} class Class extends Fn { constructor() { super(); } }
有什麼後果?規格說的是什麼?
看起來像現在的Babel,Google V8和Mozilla Spidermonkey的實現一樣,TypeScript throws
Type ‘() => void’ is not a constructor function type
如果這是一個有效的ES2015程式碼,那麼在TypeScript中處理它的正確方法是什麼?
TypeScript Part
到目前為止,ofollow,noindex" target="_blank">spec 表示,擴充套件角色必須跟隨TypeReference.而一個TypeReference 必須是A.B.C<TypeArgument>的形式,像MyModule.MyContainer<MyItem>.所以在語法上你的程式碼是正確的.但這不是打字的情況.
該規範說BaseClass必須是一個有效的typescript類.但是,規範已經過時了,如here 所示.現在,只要將表示式計算為建構函式,TypeScript就可以在extends子句中使用表示式.這個定義是,基於實現.你可以看到它here .簡單來說,如果一個表示式實現了new(){}介面,那麼一個表示式可以算作建構函式.
ES2015 Part
所以,你的問題是簡單的函式在TypeScript中不被識別為建構函式,這是有爭議的,因為ES2015規範只需要物件具有[[construct]]內部方法.雖然使用者定義的函式物件確實有它.
ES2015 在執行時需要BaseClassis a constructor .一個物件isConstructor,如果它有[[construct]]internal methd .規範說[[construct]]是Function Object 的內部方法.使用者函式是Function Objects的例項,因此它們是建構函式.但builtin function 和arrow function 可以沒有[[構造]].
例如,以下程式碼將丟擲執行時TypeError,因為parseInt是一個內建函式,沒有[[construct]]
new parseInt() // TypeError: parseInt is not a constructor
Arrow functions are like built-in functions in that both lack .prototype and any [[Construct]] internal method. So new (() => {}) throws a TypeError but otherwise arrows are like functions:
根據經驗,任何沒有原型的功能都不是新的.
在周圍工作
簡而言之,並不是每個函式都是建構函式,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的main goal 與ES3 / 5保持相容.因此,在TypeScript中新增功能是合法的,因為它在ES3 / 5中也是合法的.同時,TypeScript還旨在捕獲程式設計錯誤.擴充套件函式可能是一個錯誤,因為該函式可能不是一個明智的建構函式(例如,一個僅用於副作用的函式).延伸甚至不存在於ES3 / 5!所以TypeScript可以自由地定義自己的擴充套件使用,使得擴充套件必須與類變數配對.這使得TypeScript更加TypeSafe,與JavaScript相容.
現在,ES2015規格定稿. JavaScript還有一個擴充套件關鍵字!然後不相容來了有efforts 解決不相容.然而,仍然存在問題. ()=> void或函式型別不能是可擴充套件的,如上所述,由於內建函式.以下程式碼將中斷
var a: (x: string) => void = eval new a('booom')
另一方面,如果將ConstructorInterface引入到TypeScript中,並且實現了每個函式文字,則會出現向後的不相容性.以下程式碼現在編譯,但是當引入了ConstructorInterface時
var a = function (s) {} a = parseInt // compile error because parseInt is not assignable to constructor
當然,TS團隊可以有一個平衡這兩個選項的解決方案.但這不是一個重中之重.另外,如果salsa,TS供電的JavaScript的代號完全實現.這個問題自然就會解決.
http://stackoverflow.com/questions/34576731/inherit-es6-ts-class-from-non-class