首页 > 解决方案 > 如何在 TypeScript 中使用静态方法和构造函数签名声明接口?

问题描述

我有两个具有通用静态方法的类。添加包括静态方法实现和构造函数签名的通用接口的最佳方法是什么?

我为相应的区块链编写了实现钱包逻辑的类BitcoinHDWalletEthereumHDWallet我想添加一个通用接口HDWallet来描述与它们一起工作的逻辑,以便用户可以执行以下操作:

    const multiWallet: Array<HDWallet> = [];
    multiWallet[0] = new BitcoinHDWallet(...);
    multiWallet[1] = new EthereumHDWallet(...);

这两个类共享一些常见的静态方法。

0)如果我用abstract class它来描述接口,我不知道如何添加构造函数签名。

1)如果我使用interface,我不能添加静态方法实现。

理想情况下,我想做这样的事情:

abstract class HDWallet {
  /**
   * Return new random mnemonic seed phrase
   */
  static generateMnemonic(): string {
    return Bip39.generateMnemonic();
  }

  constructor(bip39SeedPhrase: string, password?: string, testnet?: boolean);

  abstract getAddress(addressIndex?: number) : string;

  abstract async getBalance(address? : string) : Promise<number>; 

  ...
}


class BitcoinHDWallet extends HDWallet {...}
class EthereumHDWallet extends HDWallet {...}

标签: typescriptinterfaceabstract-classstatic-methods

解决方案


没有开箱即用的方法。抽象类是最接近您想要的东西,但它确实不允许您检查该类型是否具有特定的构造函数。

一种方法是向类添加一个额外的类型参数。这可以被限制在typeof HDWallet哪个将代表基类的构造函数签名。派生类必须将自己作为此额外参数传递,然后将检查其构造函数签名以与基类签名兼容:

abstract class HDWallet<T extends typeof HDWallet> {
  /**
   * Return BIP39 12 words new random mnemonic seed phrase
   */
  static generateMnemonic(): string {
    return "";
  }

  constructor(bip39SeedPhrase: string, password?: string, testnet?: boolean) { }

  abstract getAddress(addressIndex?: number) : string;

  abstract async getBalance(address? : string) : Promise<number>; 


}


class BitcoinHDWallet extends HDWallet<typeof BitcoinHDWallet> {
  getAddress(addressIndex?: number) : string { return ""}

  async getBalance(address?: string): Promise<number> { return Promise.resolve(0);} 
}
class EthereumHDWallet extends HDWallet<typeof EthereumHDWallet> { /// error

  constructor(testnet?: boolean) { 
    super("", "", false)
  }
  getAddress(addressIndex?: number) : string { return ""}

  async getBalance(address?: string): Promise<number> { return Promise.resolve(0);} 
}

注意使用接口,您可以描述类的静态部分以及实例类型,这取决于您要验证的内容:

interface HDWalletClass {
  generateMnemonic(): string 

  new (bip39SeedPhrase: string, password?: string, testnet?: boolean): {

    getAddress(addressIndex?: number): string;

    getBalance(address?: string): Promise<number>;
  }
}
abstract class HDWallet {
  /**
   * Return BIP39 12 words new random mnemonic seed phrase
   */
  static generateMnemonic(): string {
    return "";
  }

  constructor(bip39SeedPhrase: string, password?: string, testnet?: boolean) { }

  abstract getAddress(addressIndex?: number) : string;

  abstract async getBalance(address? : string) : Promise<number>; 


}


class BitcoinHDWallet extends HDWallet {
  getAddress(addressIndex?: number) : string { return ""}

  async getBalance(address?: string): Promise<number> { return Promise.resolve(0);} 
}
class EthereumHDWallet extends HDWallet { /// error

  constructor(testnet?: boolean) { 
    super("", "", false)
  }
  getAddress(addressIndex?: number) : string { return ""}

  async getBalance(address?: string): Promise<number> { return Promise.resolve(0);} 
}
let a: HDWalletClass = BitcoinHDWallet; //ok
let b: HDWalletClass = EthereumHDWallet; // err

推荐阅读