2017-07-09 80 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