您对泛型的使用让我有些困惑,因为您似乎没有明确类型参数 variables 和您插入其中的具体类型之间的区别。更不用说您使用非 TS 术语,如 val 和 None。无论如何,以下是编译的东西,可能给你你正在寻找的那种行为:
type NotNever<T, Y=T, N=never> = [T] extends [never] ? N : Y;
// just create types, don't worry about implementation
declare class BaseComponent<In, Out, Xin=never, Xout=never> {
// make BaseComponent depend structurally on type parameters
i: In;
o: Out;
xi: Xin;
xo: Xout;
// andThen() is generic, and only accepts the right kind of other component
// only callable if Xin and Xout are *not* never
andThen<Yin, Yout>(
this: NotNever<Xin | Xout, this>,
c: BaseComponent<Xin, Xout, Yin, Yout>
): BaseComponent<In, Out, Yin, Yout>;
// run() is only callable if Xin and Xout *are* never
run(this: BaseComponent<In, Out, never, never>): void;
}
// create some concrete subclasses where parameters are set with string literal types
class Component1 extends BaseComponent<'In', 'Out', 'Xin', 'Xout'> { }
class Component2 extends BaseComponent<'Xin', 'Xout', 'Yin', 'Yout'> { }
class Component3 extends BaseComponent<'Yin', 'Yout'> { }
你可以看看它是如何工作的:
const c1 = new Component1();
const c2 = new Component2();
const c3 = new Component3();
c1.andThen(c1); // error
c1.andThen(c2); // okay
c1.andThen(c3); // error
c1.run(); // error
c2.andThen(c1); // error
c2.andThen(c2); // error
c2.andThen(c3); // okay
c2.run(); // error
c3.andThen(c1); // error
c3.andThen(c2); // error
c3.andThen(c3); // error
c3.run(); // okay
const chain = c1.andThen(c2).andThen(c3) // BaseComponent<'In', 'Out', never, never>;
chain.run(); // okay
我认为这与您想要的相似?希望有帮助;祝你好运!
编辑:做同样事情但不用担心conditional types 和polymorphic this 的另一种方法如下:
// one base class for the end of the chain
declare class EndComponent<In, Out> {
i: In;
o: Out;
run(): void;
}
// another base class for intermediate parts of the chain
declare class PipeComponent<In, Out, Xin, Xout> {
i: In;
o: Out;
xi: Xin;
xo: Xout;
// andThen() is overloaded
andThen<Yin, Yout>(
c: PipeComponent<Xin, Xout, Yin, Yout>
): PipeComponent<In, Out, Yin, Yout>;
andThen(c: EndComponent<Xin, Xout>): EndComponent<In, Out>;
}
class Component1 extends PipeComponent<'In', 'Out', 'Xin', 'Xout'> { }
class Component2 extends PipeComponent<'Xin', 'Xout', 'Yin', 'Yout'> { }
class Component3 extends EndComponent<'Yin', 'Yout'> { }
其余的应该和以前一样。再次祝你好运!