【问题标题】:Typescript: type ConstructorParameters does not accept generic打字稿:类型 ConstructorParameters 不接受泛型
【发布时间】:2020-04-13 08:20:52
【问题描述】:

使用 typescript 3.7,我有一个带有属性的接口,该属性旨在接受构造函数:

interface IConstruct<T> {
  type: new (...args:ConstructorParameters<T>) => T;
}

我的想法是IConstruct&lt;User&gt; 将有一个属性{type: User}
但是编译器告诉我 T 不能在那里使用。这是为什么呢?

TS2344:类型 T 不满足约束 'new (...args: any) => any'

【问题讨论】:

    标签: typescript types


    【解决方案1】:

    ConstructorParameters 的类型如下所示:

    type ConstructorParameters<T extends new (...args: any) => any> =
      T extends new (...args: infer P) => any ? P : never;
    

    所以类型参数T 本身必须扩展某种由约束extends new (...args: any) =&gt; any 定义的构造函数。像这样写上面的例子,你应该很高兴:

    class User {
        constructor(public name: string) { }
    }
    
    // add constructor function type constraint for T
    interface IConstruct<T extends new (...args: any) => any> {
        // we can use built-in InstanceType to infer instance type from class type
        type: new (...args: ConstructorParameters<T>) => InstanceType<T>;
    }
    
    type UserConstruct = IConstruct<typeof User>
    
    const constr: UserConstruct = {
        type: User
    }
    
    constr.type // new (name: string) => User
    
    const userInstance = new constr.type("John") // userInstance: User
    
    console.log(userInstance.name) // John
    

    Playground

    【讨论】:

    • 感谢您的提示。当您声明您的类型 T1 时,您为什么使用 typeof User 而不是 UserUser 不是已经是一个类型了吗?
    • @BeetleJuice 不完全是,有区别:User 是实例的类型,typeof User 是实际的类类型。 Here 是文档中的一个很好的例子。
    • @BeetleJuice 更新了答案以在调用IConstruct.type 构造函数时返回T 的实例类型(这可能是您想要的)。我还为示例提供了更多详细信息,希望对您有所帮助。
    • ConstructorParameters的类型定义中,? P : never是什么? never 是对从不执行的构造函数的引用——即抽象类的构造函数签名吗?
    • @CraigHicks 不,? : 构造是 conditional typenever 类型系统中的底部类型。这意味着没有任何东西可以分配给它,因此如果 TS 无法 infer 构造函数参数,您可以在此处将其用作某种类型错误指示。
    猜你喜欢
    • 2019-01-16
    • 2021-11-26
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 2018-12-27
    • 2020-06-29
    • 1970-01-01
    • 2018-04-27
    相关资源
    最近更新 更多