2017-07-09 77 views
0

目標

我最佳嘗試只是執行打字的項目,讓任何人都實現了一個動物必須提供此功能,並確保該功能只能採取兩種Woof或Meow作爲唯一參數,並且只能返回Woof或Meow。實現接口功能 - 聲稱正確實現接口

初步嘗試

下面是一些示例代碼,這是類似的(除了名稱)我在VSCode得到了代碼(使用打字稿2.4.1):

class Woof { 
    constructor(private a: boolean = true) {} 
} 

class Meow { 
    constructor(private b: string = "abc") {} 
} 

class Dog implements Animal { 
    doSomething(sound: Woof): Woof { 
     return new Woof(); 
    } 
} 

class Cat implements Animal { 
    doSomething(sound: Meow): Meow { 
     return new Meow(); 
    } 
} 

interface Animal { 
    doSomething: <T extends Woof | Meow>(input: T) => T; 
} 

如果我放棄它in the TypeScript playground ,它會產生我期望的沒有錯誤的JavaScript。

然而,VSCode內,我一直都在狗和貓類下有一個紅色的波浪線和鼠標懸停讀取所有的以下內容:

類「狗」不正確地實現了接口「動物」。

屬性'doSomething'的類型不兼容。

類型'(sound:Woof)=> Woof'不能分配給類型'(input:T)=> T'。

「聲音」和「聲音」參數的類型不兼容。

類型'T'不能指定爲'Woof'類型。

類型'Woof |喵'不能分配鍵入'Woof'。

類型'Meow'不能指定爲'Woof'。

房產「一」缺失型「喵」

每個錯誤的嵌套,所以現在還很難準確地在此處顯示的格式,但它似乎表明,我不能只指定在擴展泛型時使用Woof或Meow類型,因爲私有屬性並未在兩種類型中實現(看起來類似於another question here)。儘管在文檔中沒有看到任何表明這是非法的東西(並且在操場上,這看起來沒有問題)。但是,與那個問題不同,我不希望泛型擴展這兩種類型,而是限制爲一種或另一種。

閱讀有關交集類型的文章中的描述,它顯示「A union type A | B表示A或B類型的實體,而交集類型A表示同時爲type A和B型「。讀這個,我絕對想要一個工會類型,但這是我似乎有以上,並沒有出現採取。

這些類型在替換類下在翻轉後翻轉,但消息是相同的。

我在輸出中使用'tsc'實際構建項目時也會出現此錯誤。

交替嘗試 - 與接口更換類型每個工具

我也試過在實施希望,這將消除怪異必須讓私營性質的緯和喵類之間匹配以下(以當指定每種情況時意外的事情不起作用):

interface Sound { 
} 

class Woof implements Sound { 
    constructor(private a: boolean = true) {} 
} 

class Meow implements Sound { 
    constructor(private b: string = "abc") {} 
} 

class Dog implements Animal { 
    doSomething(sound: Woof): Woof { 
     return new Woof(); 
    } 
} 

class Cat implements Animal { 
    doSomething(sound: Meow): Meow { 
     return new Meow(); 
    } 
} 

interface Animal { 
    doSomething: <T extends Sound>(input: T) => T; 
} 

我得到和以前一樣的每個類的錯誤。

半工作版本

現在,如果我只是消除仿製藥乾脆從上面的替代僅使用界面,它解決的目標的一部分中,我可以限制參數和結果一類實現接口,但這並不完美,因爲它並不妨礙另一個開發人員傳入一個接口實現並嘗試返回另一個接口。

interface Sound { 
} 

class Woof implements Sound { 
    constructor(private a: boolean = true) {} 
} 

class Meow implements Sound { 
    constructor(private b: string = "abc") {} 
} 

class Dog implements Animal { 
    doSomething(sound: Woof): Woof { 
     return new Woof(); 
    } 
} 

class Cat implements Animal { 
    doSomething(sound: Meow): Meow { 
     return new Meow(); 
    } 
} 

interface Animal { 
    doSomething: (input: Sound) => Sound; 
} 

我更喜歡使用泛型並將T限制爲一個實現的類型安全性。關於如何使用泛型與語法實現TypeScript實際上可以在遊樂場外使用的任何想法?

+1

如何使用重載而不是泛​​型? – unional

+0

@unional我寧願不要,因爲我希望其他開發人員僅僅通過類型系統來限制(通過類型系統)來實施動物界面,並且被限制輸入一種類型並輸出相同類型,每個特定選項都在那裏在動物的功能定義本身。雖然我可以將這些類型聯合起來,但我不能僅僅將這些約束納入到通用本身中,這似乎很奇怪。 – Xaniff

回答

1

這對你有用嗎?

class Woof { 
    constructor(private a: boolean = true) { } 
} 

class Meow { 
    constructor(private b: string = "abc") { } 
} 

class Dog implements Animal<Woof> { 
    doSomething(sound: Woof): Woof { 
    return new Woof(); 
    } 
} 

class Cat implements Animal<Meow> { 
    doSomething(sound: Meow): Meow { 
    return new Meow(); 
    } 
} 

interface Animal<T extends Meow | Woof> { 
    doSomething(input: T): T; 
} 
+0

很好用 - 爲什麼消除了將約束放入界面的錯誤,而不是函數本身? – Xaniff

+1

因爲在函數上你依靠編譯器來推斷T的類型。在推斷時,我認爲它不能縮小類型。也許通過設計或者可以做出一些改進。我給出的解決方案只是使其明確。 – unional