2017-04-18 66 views
0

我已經嘗試了幾種不同的方法來在TypeScript中聲明裝飾器函數,使裝飾類實現接口。事情是這樣的:實現接口的TypeScript裝飾器聲明

interface IValidatable { 
    checkValidation:() => boolean; 
} 

function validated<T>(Class: {new():T}): {new():T & IValidatable} { 
    Class.prototype.checkValidation =() => true; 
    return Class as {new():T & IValidatable}; 
} 

鑑於上述情況,我希望我可以那麼做這樣的事情:

@validated 
class Foo { 

} 

let f = new Foo(); 
let isValid = f.checkValidation(); 

但最後一行被標記爲錯誤(「財產‘checkValidation’呢在'Foo'類型上不存在。「)。

以下確實在這個意義上工作,它並不會產生錯誤:

let ValidatedFoo = validated(Foo); 
let vf = new ValidatedFoo(); 
let isValid2 = vf.checkValidation(); 

有沒有辦法制定裝飾聲明使得第一用法示例不產生錯誤?

+2

看來這是一段時間以來一直存在的問題https://github.com/Microsoft/TypeScript/issues/4881 –

回答

1

我不認爲你可以修復它,以便裝飾器改變編譯器認爲Foo類的方式。
裝飾器在運行時工作不能編譯時間,所以當你實例化Foo時,編譯器會看到Foo

我能想到的以下三個選項:

(1)鑄造實例:

let f = new Foo() as Foo & IValidatable; 
let isValid = f.checkValidation(); 

(2)鑄類的交點:

interface FooConstructor { 
    new(): Foo & IValidatable; 
} 

let f = new (Foo as FooConstructor)(); 
let isValid = f.checkValidation(); 

(3 )使用工廠功能:

function fooFactory(): Foo & IValidatable { 
    return new Foo() as Foo & IValidatable; 
} 

let f = fooFactory(); 
let isValid = f.checkValidation(); 

code in playground

+0

感謝您的回覆。如果通過「裝飾器在運行時工作而不編譯時間,那麼當你實例化Foo時,編譯器會看到Foo。」你是在暗示這是不可能的,即使原則上,我認爲這是不正確的。這就是爲什麼我將「工作」的例子包括進去的原因:在類似的情況下,TS可以做出正確的推斷。 –

+0

我並不是說「這永遠不能工作」,現在是這樣。如果編譯器用'validate(Foo)'替換'Foo'的定義(這是你的工作示例),它就可以工作。它也可以在運行時工作,因爲js代碼有這樣的內容:'Foo = __decorate([validated],Foo)'(它也是一樣的,只發生在運行時) –