gpt4 book ai didi

javascript - TypeScript 中是否可以有通用的装饰器,可以根据其输入/输出类型进行链接?

转载 作者:行者123 更新时间:2023-12-01 01:11:42 25 4
gpt4 key购买 nike

对于我们的一些集成,我们在代码库中有相当“模板化”的实现,恕我直言,可以方便地将其放入“管道和过滤器”模式中。

“组件”可以看起来像以下类型:

class Component1<In, Out, Xin, Xout>
class Component2<Xin, Xout, Yin, Yout>
class Component3<Yin, Yout> // only has 2 params but could be <Yin, Yout, None, None> for a custom 'None' type

这个想法是有一些东西可以让这些被“链接”以允许这样的事情:

const c1 = new Component1<A,B,C,D>(...) //perhaps pass the param types in constructor? Other options?
const c2 = new Component2<C,D,E,F>(...)
const c3 = new Component3<E,F, None, None>(...)

const chain = c1.andThen(c2).andThen(c3) // The "last" item in the chain would "always" be a component of type <X,Y, None, None>

chain.run() // Not sure if this is needed but to make it clear that something "runs" this chain

我无法想到创建这些组件的任何“通用”方法,其中可以在编译时“定义”此链接以限制哪些组件可以与其他组件连接(即输入/输出类型应该匹配) 。因此,c1 后面只能跟 c2,而不能跟 c3 - 但在 c3 之后不能链接任何内容。

这可能吗?有什么办法可以让它足够接近吗?

(对于好奇的人:尝试实现 Finagle 在 Scala 世界中提供的类似“可组合性”)

最佳答案

您对泛型的使用让我有点困惑,因为您似乎没有明确类型参数变量与插入其中的具体类型之间的区别。更不用说您使用 valNone 等非 TS 术语。无论如何,以下是可以编译的内容,并且可能为您提供您正在寻找的行为:

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 typespolymorphic 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'> { }

其余部分应该像以前一样运行。再次祝你好运!

关于javascript - TypeScript 中是否可以有通用的装饰器,可以根据其输入/输出类型进行链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55108616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com