键入返回具有此属性的对象的方法吗?

时间:2019-02-20 18:51:13

标签: typescript

我如何在this.make是一个函数的情况下键入此方法

abstract class Example{
  abstract from: string;
  abstract to: string;
  make (): string {
    return 'hi';
  }
  methods () {
    return ({
      from: {
        [this.from]: {
          to: {
            [this.to]: this.make,
          },
        },
      },
    });
  }
}
class Move extends Example {
  from = 'alpha';
  to = 'beta';
}

const x = (new Move()).methods().from;

enter image description here

2 个答案:

答案 0 :(得分:1)

您可以在函数的返回类型注释中使用多态this来执行此操作。您将需要使用类型断言来使实现起作用,但是派生类将按预期方式键入。

还需要将派生类中的字段显式地键入为字符串文字类型,或者将其声明为只读,以使编译器不会将类型扩展为string

type MethodResult<TFrom extends string, TTo extends string> = {
    from: Record<TFrom, {
        to: Record<TTo, string>
    }>
}
abstract class Example{
  abstract from: string;
  abstract to: string;
  make (): string {
    return 'hi';
  }
  methods () : MethodResult<this['from'],this['to']> {
    return ({
      from: {
        [this.from]: {
          to: {
            [this.to]: this.make,
          },
        },
      },
    }) as any;
  }
}
class Move extends Example {
  readonly from = 'alpha';
  readonly to = 'beta';
}

const x = (new Move()).methods().from.alpha.to.beta;

答案 1 :(得分:0)

Typescript是一种编译时语言。因此,通常无法进行运行时键入,并且this的状态从根本上讲是运行时状态。

单个抽象类型肯定有可能根据实现返回不同的内容,但这必须在编译时完成。

因此,如果您不熟悉此功能,则通用工具是泛型。

这是一个例子,它不能完全做到您想要的,但可以给您一些接近的东西。

type MoveAbstract = {
  from: {
     [s:string]: {
       to: {
         [s: string]: () => string
       }
     }
  }
}

abstract class Example<T extends MoveAbstract> {
  abstract from: string;
  abstract to: string;
  make (): string {
    return 'hi';
  }
}

type MakeMove = {
  from: {
     alpha: {
       to: {
         beta: () => string
       }
     }
  }
}

class Move extends Example<MakeMove> {
  from = 'alpha';
  to = 'beta';
  methods (): MakeMove {
    return ({
      from: {
        alpha: {
          to: {
            beta: this.make,
          },
        },
      },
    });
  }

}

const x = (new Move()).methods().from;

我意识到这并不是您想要的完全是 ,并且重复次数可能比您想要的要多,但从{{1}的使用者的角度来看}抽象类,您基本上可以完成这项工作。

也许可以进一步优化,但是我不确定!