我正在尝试编写一些模式,允许对象在没有类继承的情况下扩展另一个对象,以实现松散耦合和函数方法(我在样本中用“extend”函数表示,也可能是称为“管道”)。这很容易。但所有这些都保留了打字。这很难。
我想知道如何按照流程获得Typescript类型。
以下是示例(link for Typescript playground)的简化代码段:
abstract class DecoratorAbstract {
public parent: DecoratorAbstract;
public extend<T extends DecoratorAbstract>(decorator: T): T {
decorator.parent = this;
return decorator;
}
abstract decorate(): {}
}
class InitialDecorator extends DecoratorAbstract {
decorate() {
return { var: 'value' } as { 'var': string };
}
}
class Decorator1 extends DecoratorAbstract {
decorate() {
let result = this.parent.decorate();
let newResult = Object.assign(result, { 'foo': 'foo' });
return newResult;
}
}
class Decorator2 extends DecoratorAbstract {
decorate() {
let result = this.parent.decorate();
let newResult = Object.assign(result, { 'bar': 'bar' });
return newResult;
}
}
// Split to show the return types
let initialDecorator = new InitialDecorator();
let r0 = initialDecorator.decorate();
let decorator1 = initialDecorator.extend(new Decorator1);
let r1 = decorator1.decorate();
let decorator2 = decorator1.extend(new Decorator2);
let r2 = decorator2.decorate();
console.log(r2);
// The syntax I seek
let someDecorator = new InitialDecorator()
.extend(new Decorator1);
.extend(new Decorator2);
let someResult = someDecorator.decorate();
// The type I seek:
// {var: string} & {foo: string} & {bar: string}
我得到的打字:
{} & {'foo': string;}
的{{1}}和r1
的{{1}},将{} & {'bar': string;}
的返回类型替换为r2
(抽象函数的结果),而不是真实的类型。
所以我想知道:
decorator.parent.decorate
{}
但是我的集合对象类型必须在开头就知道,并且对于所有项目都是相同的。也许我没有以正确的方式做到这一点。
这是有效的:
public extend<T extends DecoratorAbstract>(decoratorName: { new (): T }) {
let decorator = new decoratorName();
decorator.parent = this;
return decorator;
}
我可以创建一个对象链并保留它们的类型。 但它没有那么多帮助...... 一旦遇到这个这个词,就不再遵循这些类型了(回到Abstract类)。
我没有成功使 Typescript 保留我的对象类型。主要是因为:
我认为我的问题可以通过设计链接列表或集合的方式来解决,该列表可以保留每个元素的类型。
我认为我的尝试接近于解决方案......
但我总是依赖的问题是以下(test it in Typescript playground):
class Piper<T extends {parent: PARENT}, PARENT> {
public obj: T;
public parent: PARENT;
constructor(obj: T, parent: PARENT) {
this.obj = obj;
this.obj.parent = this.parent as PARENT;
}
out(): T {
return this.obj;
}
}
问题很简单:我希望对象class Link<OBJ, PARENTLINK> {
constructor(public obj: OBJ, public parent:PARENTLINK = null) {}
pipe<NEWOBJ>(newObj: NEWOBJ):Link<NEWOBJ, this> {
return new Link(newObj, this);
}
}
abstract class DecoratorAbstract {
abstract decorate<T>(result: T): {}
}
class InitialDecorator extends DecoratorAbstract {
decorate<T>(result:T) {
return { var: 'value' } as { 'var': string };
}
}
class Decorator1 extends DecoratorAbstract {
decorate<T>(result:T) {
let newResult = Object.assign(result, { 'foo': 'foo' });
return newResult;
}
}
class Decorator2 extends DecoratorAbstract {
decorate<T>(result:T) {
let newResult = Object.assign(result, { 'bar': 'bar' });
return newResult;
}
}
let l = new Link(new InitialDecorator);
let l1 = l.pipe(new Decorator1);
let l2 = l1.pipe(new Decorator2);
调用注入对象abstract class BaseObj<P> {
parent: P
abstract test(): {}
}
class A<P extends BaseObj<any>> extends BaseObj<P> {
test() {
return this.parent.test();
}
}
class B<P extends BaseObj<any>> extends BaseObj<P> {
test() {
return {hop: 'la'};
}
}
// let c = new A(); // Won't work
let c = new A<B<any>>();
c.parent = new B;
c.parent.test(); // return type: {hop: string}
的方法(在下面的例子中,嵌入的注入对象)。
为了以一般方式可行:
A
必须知道B
的类型,否则会使用它扩展的类型它适用于这个例子,因为一切都非常具体,但不是:
A
我想要的是一些允许注入类/对象的函数,这样:
B
或let c = new A<B<any>>();
c.parent = new B;
问题在于我没有设法退出pipe(MyObj, new InjectedObj());
函数let a = pipe(new MyObj(), new InjectedObj());
的{{1}}实例,pipe
,A
...
检测A<B<any>>
条目中的类型不是问题。但让对象知道另一个(注入的)对象类型是我总是失败的地方......
无论我写它的方式如何,都要回到这个问题上。
我的尝试:
答案 0 :(得分:1)
如果未在任何地方定义,则TypeScript无法知道返回类型a
。如果要在运行时挂载管道,它只会在运行时知道它的类型。
如何将其定义为最终回报,例如A<B<any>>
?它仍然可以调用A<string>
,但最后,重要的是最终结果将是一个字符串。
B
答案 1 :(得分:0)
使用极简主义功能方法管理泛型可能更容易:
const decorate1 = <T>(item: T) => Object.assign({}, item, { b: 'b' })
const decorate2 = <T>(item: T) => Object.assign({}, item, { c: 'c' })
const multiDecorate = <T>(item: T) => decorate2(decorate1(item));
const initial = { a: 'a' };
const multiDecorated = multiDecorate(initial);
console.log({ multiDecorated });
Try it in TypeScript Playground
类型流过,因此multiDecorated
是交集类型:
{} & { a: string; } & { b: string; } & { c: string; }