typescript - 根据 typescript 中的构造函数参数重载类属性

标签 typescript typescript-typings typescript-generics

在我们的代码库中,我们广泛使用导航器和构建器模式来抽象组装分层对象。其核心是 Navigator我们用它来遍历不同的类。我目前正在尝试将其迁移到 typescript ,但正在努力输入它以利用 typescript 的力量。

我认为我的问题的核心是我无法使用this作为类上泛型的默认值,例如class Something<T = this> ,或者我无法重载该类以某种方式有条件地设置类属性的类型。您能否提供有关我如何输入 Navigator 的任何见解? (和构建器类)在下面吗?

// I guess what I'd like to do is
// class Navigator<BackT = this> but that's not allowed
class Navigator<BackT> {
  // It's this 'back' type I'll like to define more specifically
  // i.e. if back is passed to the constructor then it should be 'BackT'
  //      if back is not passed to the constructor or is undefined, it 
  //      should be 'this'
  back: BackT | this; 

  constructor(back?: BackT)  {
    this.back = back || this;
  }
}

class Builder1<BackT> extends Navigator<BackT> {
  builder1DoSomething() {
    // Do some work here
    return this;
  }
}

class Builder2<BackT> extends Navigator<BackT> {
  withBuilder1() {
    return new Builder1(this);

    // Also tried the following, but I got the same error:
    // return new Builder1<this>(this);
  }

  builder2DoSomething() {
    // Do some work here
    return this;
  }
}

// This is fine
new Builder1().builder1DoSomething().builder1DoSomething();

new Builder2()
  .withBuilder1()
  .builder1DoSomething()
  // I get an error here becuase my types are not specific enough to
  // let the complier know 'back' has taken me out of 'Builder1' and
  // back to 'Builder2'
  .back.builder2DoSomething();

playground link

最佳答案

如果没有向类提供类型参数,您可以在 back 字段上使用条件类型将其键入为 this。我们将使用 void 类型作为默认值来表示缺少类型参数:

class MyNavigator<BackT = void> {
  back: BackT extends void ? this : BackT; // Conditional type 

  constructor(back?: BackT)  {
    this.back = (back || this) as any;
  }
}

class Builder1<BackT = void> extends MyNavigator<BackT> {
  builder1DoSomething() {
    return this;
  }
}

class Builder2<BackT = void> extends MyNavigator<BackT> {
  withBuilder1() {
    return new Builder1(this);
  }
  builder2DoSomething() {
    return this;
  }
}

new Builder2()
  .withBuilder1()
  .builder1DoSomething()
  // ok now
  .back.builder2DoSomething();

关于typescript - 根据 typescript 中的构造函数参数重载类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56887863/

相关文章:

reactjs - 将 ts-jest 与 create-react-app 一起使用

angular - 与客户类型一样

typescript - 具有属性的类,其中属性本身包含 <T extends Class> 类型的属性

typescript - 如何让 TS 在通用构建器函数中推断回调?

Typescript 联合类型和推断不同的属性,无需额外的类型检查

html - 如何从调用另一个组件的组件发送数据

javascript - 将 TypeScript 对象传递给 Electron 应用程序中的 Window

typescript 3.x : Access properties of type unknown

typescript - 如何在 Angular 2 中包含 typescript 自定义类型定义?

typescript - TypeScript Vue 组件中的泛型