Javascript TypeScript中是否可能有可以根据其输入/输出类型链接的泛型装饰器?
对于我们的一些集成,我们在代码库中有相当“模板化”的实现,可以方便地放入“管道和过滤器”模式IMHO中 “组件”可以做成如下类型:Javascript TypeScript中是否可能有可以根据其输入/输出类型链接的泛型装饰器?,javascript,typescript,decorator,finagle,Javascript,Typescript,Decorator,Finagle,对于我们的一些集成,我们在代码库中有相当“模板化”的实现,可以方便地放入“管道和过滤器”模式IMHO中 “组件”可以做成如下类型: 类组件1 类组件2 类Component3//只有2个参数,但可以是自定义的“None”类型 我们的想法是让这些东西被“链接”起来,这样可以实现: const c1 = new Component1<A,B,C,D>(...) //perhaps pass the param types in constructor? Other options? c
类组件1
类组件2
类Component3//只有2个参数,但可以是自定义的“None”类型
我们的想法是让这些东西被“链接”起来,这样可以实现:
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
const c1=new Component1(…)//是否在构造函数中传递参数类型?其他选择?
常数c2=新组件2(…)
常数c3=新组件3(…)
const chain=c1.第(c2).第(c3)//链中的“最后”项将“始终”是类型的组件
chain.run()//不确定是否需要这样做,但要明确有什么东西在“运行”这个链
我想不出任何创建这些组件的“通用”方法,在编译时可以“定义”这种链接,以限制哪些组件可以与其他组件连接(即,输入/输出类型应该匹配)。因此,c1
只能跟在c2
后面,而不能跟在c3
后面,但是在c3
后面不能链接任何内容
这可能吗?有什么能让它足够靠近的吗
(对于好奇的人:试图实现类似于Finagle在Scala世界中提供的“可组合性”)我对泛型的使用有点困惑,因为您似乎没有弄清楚类型参数变量和插入其中的具体类型之间的区别。更不用说使用非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'> { }
其他人应该像以前一样。祝你好运 您对泛型的使用让我有点困惑,因为您似乎没有弄清楚类型参数变量和插入其中的具体类型之间的区别。更不用说使用非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'> { }
其他人应该像以前一样。祝你好运 以下是我得到的:
class Component<T, U> {
constructor(private t: T, private u: U) {}
andThen<V>(component: Component<U, V>): Component<U, V> {
// implement andThen
return component;
}
static run<T>(component: Component<T, null>) {
// implement run
}
}
type A = 'a'; const a: A = 'a';
type B = 'b'; const b: B = 'b';
type C = 'c'; const c: C = 'c';
const c1 = new Component<A, B>(a, b);
const c2 = new Component<B, C>(b, c);
const c3 = new Component<C, null>(c, null);
c2.andThen(c1); // TS2345: A is not assignable to B
Component.run(c1.andThen(c2)); // TS2345: Component<B,C> not assignable to Component<B,null>
Component.run(c1.andThen(c2).andThen(c3));
我希望这就是你要找的东西。这是我得到的:
class Component<T, U> {
constructor(private t: T, private u: U) {}
andThen<V>(component: Component<U, V>): Component<U, V> {
// implement andThen
return component;
}
static run<T>(component: Component<T, null>) {
// implement run
}
}
type A = 'a'; const a: A = 'a';
type B = 'b'; const b: B = 'b';
type C = 'c'; const c: C = 'c';
const c1 = new Component<A, B>(a, b);
const c2 = new Component<B, C>(b, c);
const c3 = new Component<C, null>(c, null);
c2.andThen(c1); // TS2345: A is not assignable to B
Component.run(c1.andThen(c2)); // TS2345: Component<B,C> not assignable to Component<B,null>
Component.run(c1.andThen(c2).andThen(c3));
我希望这就是您要找的。这很有趣。尤其是带有多态this和条件类型的。编辑案例也相当有趣。我绝对可以玩这个
None
被暗指为“自定义类型”,而不是TS的一部分。将val
修复为const
也-忘记了这一点。但是谢谢你的建议,也谢谢你花时间帮忙。这可能只是工作:)但为什么字符串文字在参数中,而不是实际类型@jcalzString文本:除了方便之外,没有其他原因。如果您有真正的类型,您应该能够在它们的位置使用它们。第二个实现似乎需要一个run
方法,不是吗?这很有趣。尤其是带有多态this和条件类型的。编辑案例也相当有趣。我绝对可以玩这个None
被暗指为“自定义类型”,而不是TS的一部分。将val
修复为const
也-忘记了这一点。但是谢谢你的建议,也谢谢你花时间帮忙。这可能只是工作:)但为什么字符串文字在参数中,而不是实际类型@jcalzString文本:除了方便之外,没有其他原因。如果您有真正的类型,您应该能够在它们的位置使用它们。第二个实现似乎需要一个run
方法,不是吗?
class Component<T, U> {
constructor(private t: T, private u: U) {}
andThen<V>(component: Component<U, V>): Component<U, V> {
// implement andThen
return component;
}
static run<T>(component: Component<T, null>) {
// implement run
}
}
type A = 'a'; const a: A = 'a';
type B = 'b'; const b: B = 'b';
type C = 'c'; const c: C = 'c';
const c1 = new Component<A, B>(a, b);
const c2 = new Component<B, C>(b, c);
const c3 = new Component<C, null>(c, null);
c2.andThen(c1); // TS2345: A is not assignable to B
Component.run(c1.andThen(c2)); // TS2345: Component<B,C> not assignable to Component<B,null>
Component.run(c1.andThen(c2).andThen(c3));
(new Component<'a', 'b'>('a', 'b'))
.andThen(new Component<'b', 'c'>('b', 'c'))
.andThen(new Component<'c', 'd'>('c', 'd'))
.andThen(new Component<'d', 'e'>('d', 'e'))
.andThen(new Component<'e', 'f'>('e', 'f'))
.andThen(new Component<'f', 'g'>('f', 'g'))