【问题标题】:How to make TypeScript infer the type of dynamic new() calls如何让 TypeScript 推断动态 new() 调用的类型
【发布时间】:2020-03-17 07:30:42
【问题描述】:

我正在动态创建子类,我希望工厂函数知道子类的返回类型。

我可以通过强制转换来做到这一点,但我想知道是否有一种方法可以在不需要强制转换的情况下推断它。

class Hello { 
  a = 1;
}

class Hello2 extends Hello{ 
  b = 2; 
}

class Hello3 extends Hello { 
  c = 3; 
}

function create<T extends typeof Hello>(ctor: T): InstanceType<T> {
  // If I don't cast this, it won't compile
  return new ctor() as InstanceType<T>;
}

// Fails as it should because it's not a constructor of the right type
const h1 = create(Number);
const h2 = create(Hello2); 
console.log(h2.b); // no error
const h3 = create(Hello3);
console.log(h3.c); // no error

【问题讨论】:

    标签: typescript type-inference


    【解决方案1】:

    如果您改为使类实例通用(而不是静态侧/构造函数)怎么办?这应该适合你,比如here:

    class Hello { 
      a = 1;
    }
    
    class Hello2 extends Hello{ 
      b = 2; 
    }
    
    class Hello3 extends Hello { 
      c = 3; 
    }
    
    function create<T extends Hello>(ctor: new() => T) {
      return new ctor()
    }
    
    const h1 = create(Number); // error
    const h2 = create(Hello2); // h2: Hello2
    console.log(h2.b); // no error
    const h3 = create(Hello3); // h3: Hello3
    console.log(h3.c); // no error
    

    如果需要,您可以定义要传递的其他参数,例如 create&lt;T extends Hello&gt;(ctor: new(...args: any[]) =&gt; T) 或更具体的方式。

    【讨论】:

    • 听起来很有希望,我不明白为什么我的不起作用,但让我用我的实际代码试一试。
    • 您的示例肯定是朝着正确的方向发展,并且受到编译器无法对条件类型(InstanceType 是一个)与未解析的泛型类型参数(T)相结合的假设的限制。这样的星座几乎总是需要类型断言。如果像上面这样写,可以省略条件类型,它会再次正确输入。
    • 这种方法的问题是我必须复制Hello 的签名,在我的情况下需要特定参数,如果我想要那里的类型安全。我总是可以将其设为any...,这将是一个权衡,any 而不是cast,我认为演员会更安全。话虽如此,这肯定回答了问题。
    • 我想过不要使用ConstructorParams 复制参数,但我无法弄清楚如何使用它。我稍后会发布一个关于此的问题。 github.com/Microsoft/TypeScript/blob/master/lib/…
    • ConstructorParams 会导致类似的问题,因为它也是一个条件。类型。您需要在要实例化的子类的参数上使其通用(或所有类都具有相同的参数)。无论是否类型断言,我都会选择在这种情况下最容易实现的。最后,断言并不是一件坏事(来自前 Java 开发人员的声明;),因为它很好地封装在 create 函数中,并且函数的调用者不必费心。如果需要,您可以实施运行时检查,或者稍后替换强制转换,如果 TS 应该变得更智能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 2023-02-05
    • 2018-07-03
    • 1970-01-01
    相关资源
    最近更新 更多