方法中泛型类的 TypeScript 类型约束

问题描述 投票:0回答:1

我需要一个泛型类来“扩展”方法中的泛型:

  class Foo<T> {
      constructor(public t: T) {}

      do<B>(f: (b: B) => void) {
          f(this.t); // error
      }
  }

以下内容失败:

Argument of type 'T' is not assignable to parameter of type 'B'.
'B' could be instantiated with an arbitrary type which could be unrelated to 'T'.

f(this.t);

如何约束 B 使得

T extends B

这是一个更复杂的例子,其中

push
函数产生相同的错误:

type Template = { content: string };
type Render = (tpl: Template) => void;

type Cont<Out> = (arg: { state: Out}) => void;

type Step<In, Out> = {
  template: (args: {
    next: (arg: Out) => void;
    state: In;
  }) => Template;
};

class Wizard<Out> {
  constructor(public run: (arg: { cont: Cont<Out>; render: Render }) => void) {}

  static init<Out>(step: Step<{}, Out>): Wizard<Out> {
    return new Wizard(({ cont, render }) => {
      const state = {};
      const tpl = step.template({
        state,
        next: (state1) =>
          cont({ state: { ...state1, ...{} }}),
      });
      render(tpl);
    });
  }

  /*
  push<In1, Out1>(
    step: Step<In1, Out1>
  ): Wizard<Ouut & Out1> {
      const wizz: Wizard<Out> = this;
      const run: (arg: { cont: Cont<Out>; render: Render}) => void = wizz.run;
    return new Wizard<Out & Out1>(({ cont, render }) =>
      run({
        cont: ({ state, }: { state: Out; }) => {
          const tpl = step.template({
            state,
            next: (state1) =>
              cont({
                state: { ...state1, ...state },
              }),
          });
          render(tpl);
        },
        render,
      })
    );
  }
  */
}

这是一个有效的等效函数(尽管接口不如类好):

  type Wizz<Out> = (
    cont: (out: Out, back: () => void | undefined) => void,
    render: Renderer
  ) => void;

  const init =
    <Out>(step: Step<{}, Out>): Wizz<Out> =>
    (cont, render) => {
      const state = {};
      const back = undefined;
      const tpl = step.template({
        state,
        back,
        next: (state1) => cont({ ...state1, ...{} }, () => render(tpl)),
      });

      render(tpl);
    };

  const push = <In1, Out extends In1, Out1>(
    wizz: Wizz<Out>,
    step: Step<In1, Out1>
  ): Wizz<Out & Out1> => {
    return (cont, render) => {
      wizz((state, back) => {
        const tpl = step.template({
          state,
          back,
          next: (state1) => cont({ ...state1, ...state }, () => render(tpl)),
        });
        render(tpl);
      }, render);
    };
  };
typescript oop type-systems
1个回答
0
投票

您可以像这样限制 T 来扩展 B,但正如@jcalz 提到的那样,此示例中没有真正的好处。

class Foo<B, T extends B> {
  constructor(public t: T) { }
  do<B>(f: (b: T) => void,) {
    f(this.t); // no error
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.