基于打字稿中的构造函数参数重载类属性 [英] Overloading class properties based on constructor arguments in typescript

查看:25
本文介绍了基于打字稿中的构造函数参数重载类属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In our codebase we use a navigator and builder patterns pretty extensively to abstract away assembling hierarchical objects. At the heart of this is a Navigator class which we use to traverse different classes. I'm currently attempting to migrate this to typescript but am struggling to type it to leverage the power of typescript.

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

I think the core of my problem is that I can't use this as the default value for a generic on a class e.g. class Something<T = this>, or that I can't overload the class to somehow conditionally set the types of class properties. Can you provide any insights into how I might be able to type the Navigator (and builder classes) below?

// 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();

操场链接

推荐答案

如果没有类型参数,您可以在 back 字段上使用条件类型将其键入为 this被提供给班级.我们将使用 void 类型作为默认类型来表示没有类型参数:

You can use a conditional type on the back field to type it as this if no type argument was supplied to the class. We will use the void type as the default to signal the absence of a type argument:

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();

这篇关于基于打字稿中的构造函数参数重载类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆