将 class 定义作为参数传递并在 TypeScript 中引用静态成员

Pass class definition as parameter & reference static member in TypeScript

我试图将 class 定义作为参数传递给函数,然后在函数内部访问 class 的静态成员,但 Typescript 说静态 属性该类型不存在,并询问我是否要访问静态成员。我知道,但无法弄清楚如何以允许的方式指定参数的类型。感觉这应该很简单,我只是遗漏了一些小细节,但是它是什么?

代码示例,引用 this library:

import Web3 from 'web3';

//With a first param typed Web3 regardless of name, Typescript throws an error:
//Property 'providers' does not exist on type 'Web3'.
//Did you mean to access the static member 'Web3.providers' instead?ts(2576)
const getWebSocketProvider = function(
        Web3ClassDefinition: Web3, 
        host: string, 
        port: string
    ) {
    //Custom options and other components motivating use of a wrapper function
    //are removed for this minimal example.
    //Adding .constructor just before .providers changes the error to
    //"Property 'providers' does not exist on type 'Function'.ts(2339)"
    //Adding .prototype.constructor just before .providers changes the error to
    //"Property 'prototype' does not exist on type 'Web3'.ts(2339)"
    return new Web3ClassDefinition.prototype.constructor.providers.WebsocketProvider(
        'wss://'+host+':'+port
    );
};

//This call also has an error:
//Argument of type 'typeof Web3' is not assignable to parameter of type 'Web3'.
//Type 'typeof Web3' is missing the following properties from type 'Web3':
//defaultAccount, defaultBlock, currentProvider, setProvider, and 5 more.ts(2345)
// solves that, 
//but then the main error changes to
//"Property 'providers' does not exist on type Constructor<Web3>."
getWebSocketProvider(Web3, '123.45.67.89', '1234');

请注意,GPL 许可库 (index.d.ts) 中的类型定义包括静态 providers 成员:

export default class Web3 {
    constructor();
    constructor(provider: provider);
    constructor(provider: provider, net: net.Socket);
    //...
    static readonly providers: Providers;
    //...
}

问题是类型 Web3 表示 Web3 class 的实例而不是 class 本身。要将 class 本身作为参数传递,您需要使用类型 typeof Web3。这也是有点神秘的类型错误试图传达的内容:Argument of type 'typeof Web3' (i.e. actual parameter Web3) is not assignable to parameter of type 'Web3' (i.e. formal parameter Web3ClassDefinition).

如果将 Web3ClassDefinition 的类型更改为 typeof Web3,并删除 .prototype.constructor 部分,代码类型检查:

const getWebSocketProvider = function(
        Web3ClassDefinition: typeof Web3, 
        host: string, 
        port: string
    ) {
    return new Web3ClassDefinition.providers.WebsocketProvider(
        'wss://'+host+':'+port
    );
};

TypeScript playground