鉴于以下内容:
interface Component {}
interface Composite<component extends Component> {
getChildren(): component[];
}
class StackSegment implements Component {}
class Stack implements Composite<StackSegment> {
getChildren(): StackSegment[] {
return new Array<StackSegment>();
}
}
为什么以下会导致编译错误?
class Bar<component extends Component = StackSegment,
composite extends Composite<component> = Stack> {
}
我得到的错误(在Stack上作为复合的默认值)表示StackSegment不能分配给&#39;组件&#39;。
答案 0 :(得分:1)
我认为,问题在于第二种类型参数取决于第一种。我的意思是,如果第一个参数是P
类型,那么第二个参数必须是Composite<P>
类型(假设P
implments Component
)。
但是在分配默认类型时,您可以这样做:
let b = new Bar<P>();
这里我没有传递第二个类型参数,因此TypeScript假设它是Stack
。但是,Stack
不会延伸P
。
类型参数的默认值并不总是强制执行类型约束,因此无法声明此类型。
答案 1 :(得分:1)
注意:在下面我将使用类型参数的短大写标识符作为常规约定。您可以随意将CN
替换为component
,将CS
替换为composite
(但我建议不要使用常规类型参数的常规标识符)
我不确定您的用例是什么,但默认类型参数不设置约束。在您的代码中,
class Bar<CN extends Component = StackSegment,
CS extends Composite<CN> = Stack> { // error
}
类型参数CN
不是必需为StackSegment
,因此Stack
无法满足Composite<CN>
的约束。处理它的一种方法是使复合词仅Composite<CN>
而不是Stack
:
class Bar<CN extends Component = StackSegment,
CS extends Composite<CN> = Composite<CN>> { // okay
}
如果确实想要将默认值视为Stack
(例如,如果Stack
有一些仅Composite<CN>
没有的额外方法),那么你可以这样做:
class Bar<CN extends Component = StackSegment,
CS extends Composite<CN> = Stack & Composite<CN>> { // okay
}
因为Stack & Composite<StackSegment>
与Stack
的结构类型相同。但同样,我不知道你的用例。截至目前,您可以获得以下内容:
interface OtherComponent extends Component {
thingy: string;
}
class OtherComposite implements Composite<OtherComponent> {
getChildren(): OtherComponent[] {
throw new Error("Method not implemented.");
}
}
new Bar(); // Bar<StackSegment, Stack> as desired
new Bar<OtherComponent, OtherComposite>(); // also makes sense
// but this is a Bar<OtherComponent, Stack & Composite<OtherComponent>>
new Bar<OtherComponent>(); // wha?
// which is weird.
您是否打算只使用一个默认参数?如果没有,也许有更好的方式来表示泛型。但是如果没有更多的用例信息,我不知道如何建议你。
祝你好运。 编辑:一种丑陋的语法,按照我想的方式工作,就是在一个参数中指定两种类型,如下所示:class Bar<CC extends [Component, Composite<CC[0]>]=[StackSegment, Stack],
CN extends CC[0] = CC[0],
CS extends CC[1] = CC[1]> {
}
在上面,CC
是具有所需约束的两元组类型(第二个参数必须与第一个参数的Composite<>
兼容),并且它默认为对{根据需要{1}}。 ([StackSegment, Stack]
和CN
类型就是为了方便起见,因此您不需要对组件类型使用CS
,对于复合类型使用CC[0]
。
现在行为是这样的:
CC[1]
但你不能像以前那样轻易打破它:
new Bar(); // CN is StackSegment and CS is Stack, as desired
new Bar<[OtherComponent, OtherComposite]>(); // also makes sense
好的,祝你好运!
答案 2 :(得分:0)
更改导致编译器错误的代码行,如下所示:
class Bar<component extends Component = StackSegment,
composite extends Composite<Component> = Stack> {}
消除了错误。
现在的问题是,它会在被覆盖时按预期工作。