实现通用类型的Typescript通用类

时间:2018-08-23 23:44:35

标签: javascript typescript generics

是否可以将以下代码转换为通用打字稿代码?我想要一个实现某些接口 A 的类,该类接受两个 A 类型的元素,并为接口 A 的属性返回不同的值取决于一些布尔标志。我看了打字稿的泛型和自定义类型,但无法弄清楚。

从本质上讲,我希望元素在应用程序的方向每次发生变化时,都无需使用mySprite.setPosition(new Vector(10,10))之类的东西就能以纵向和横向返回不同的值。我出于好奇而问这个问题,我不是在寻找这种情况的其他解决方案,我知道还有更多解决方案。

我可以定义一些通用类型,例如 Variant ,以便对于我的子画面具有的 A 类型的任何属性,我可以进行类似mySprite.myPropOfTypeA=new Variant<A>(new A("landscape value"), new A("portrait value"))的操作mySprite.myPropOfTypeA.value根据isLandscape()的结果返回不同的值?我希望这是通用的,这样我就不必为我想要表现的每个属性创建一个派生类。谢谢!

interface IVector{
    x:number,
    y:number;
}

class Vector implements IVector{
    private _x:number;
    private _y:number;

    public get x() {return this._x;}
    public get y() {return this._y;}

    constructor(x:number, y:number){
        this._x=x;
        this._y=y;
    }
}

class VariableVector implements IVector{

    private _landscape: IVector;
    private _portrait: IVector;

    constructor(landscape: IVector, portrait: IVector){
        this._landscape=landscape;
        this._portrait=portrait;
    }

    public get x() {return isLandscape()? this._landscape.x:this._portrait.x;}
    public get y() {return isLandscape()? this._landscape.y:this._portrait.y;}

}

let mySprite=new Sprite(new VariableVector(new Vector(0,0), new Vector(10,10)));

谢谢!

2 个答案:

答案 0 :(得分:2)

以编程方式更改A上的 all 属性读值的功能并不是class真正为您提供的功能(尤其是因为无法扩展通用类型... class Variant<A> extends A无效)。在这种情况下,您真正​​想要使用的是Proxy。冒给您不想要的答案的风险(不确定是否违反“我不寻求这种情况的其他解决方案”),这是制作此类Proxy对象的一种方法:

function makeVariant<A extends object>(
  condition: () => boolean, 
  trueValue: A, 
  falseValue: A
): A {
  return new Proxy(trueValue, {
    get(target, prop: keyof A, receiver) {
      return condition() ? trueValue[prop] : falseValue[prop];
    }
  });
}

函数makeVariant接受一个回调和两个通用类型A的值,并返回一个对象,该对象的属性将根据一个回调或另一个值返回{{1} }或true。我不确定您是否希望回调函数的范围不在false定义的范围内,因此不需要将其作为参数传递,但是如果需要,您可以摆弄一下它。

让我们看看它是否有效:

makeVariant

我觉得合理。希望能为您指明有用的方向。祝你好运!

答案 1 :(得分:0)

我想我正确理解了你:)

class IPosition {
  constructor(public x: number, public y: number, public value: string) {}
}

class Variant<T extends IPosition> {
  constructor(private _landscape: T, private _portrait: T) {}

  public get x() { return isLandscape() ? this._landscape.x: this._portrait.x; }
  public get y() { return isLandscape()? this._landscape.y:this._portrait.y; }
}

const myPropOfTypeA = new Variant<IPosition>(new IPosition(0, 0, "landscape value"), new IPosition(10, 10, "portrait value"));

随时在评论中提问,将尝试更改示例以适合您的任务。

还创建了一个stackblitz example