2017-04-03 68 views
1

什麼導致此代碼失敗?Typescript中的接口上的類級通用約束

interface ISomeData { 
    name: string; 
} 

class SomeData implements ISomeData { 
    name: string = "adam"; 
} 

class SomeClass<T extends ISomeData> { 
    constructor(dataTemplate?: T) { 
     this.dataTemplateInternal = dataTemplate; 
    } 

    private dataTemplateInternal: T; 

    public initSomeData() : T { 
     let data: T = new SomeData(); 
     if (this.dataTemplateInternal) { 
      return this.dataTemplateInternal; 
     } 
     return data; 
    } 
} 

的「initSomeData」第一行有一個錯誤,說

類型「SomeData」是不能分配給輸入「T」

但因爲我的通用的限制是基於SomeData實現的接口應該不夠嗎?

Ridiculously long link to this code in the TypeScript Playground

回答

2

如果你會怎麼做:

let data: ISomeData = new SomeData(); 

你不會得到這個錯誤,但T不是ISomeData,這是什麼「更」比ISomeData,例如,它可以是:

interface IMoreData extends ISomeData { 
    username: string; 
} 

然後你說:

let data: IMoreData = new SomeData(); 

這是不正確的,因爲它缺少username財產。
,你可以告訴你知道你在做什麼(AKA鑄造)編譯器解決這個問題:

let data: T = new SomeData() as T; 

或者只是:

let data = new SomeData() as T; 
+0

謝謝,原來如此!我有點想這就是我需要做的,不知道爲什麼我不試試它! –

+0

就像一個側面問題,不是約束,指出「你的實現必須是[THIS]的最小值」(在我的情況下'接口ISomeData {名稱:字符串}'),並沒有實現該接口,以確保它有「名稱:字符串」?我仍然不明白爲什麼它不會在這裏隱含地理解我的意圖。這是通過設計,還是像語言規範中的「待辦事項」? :)不過,你搖滾,謝謝! –

+1

是的,通用約束保證'name'存在於'T'中,但**'T' **不是**'ISomeData',所以編譯器會警告你。如果你有一個'SomeClass '的實例,那麼'initSomeData'的結果應該是'IMoreData'類型而不是'ISomeData' –