我有两个使用通用静态方法的类。添加包括静态方法实现和构造函数签名的通用接口的最佳方法是什么?
我编写了BitcoinHDWallet
和EthereumHDWallet
类,它们为对应的区块链实现了钱包逻辑。我想添加公共接口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 {...}
答案 0 :(得分:1)
没有开箱即用的功能。抽象类是您想要的最接近的类,但实际上不允许您检查类型是否具有特定的构造函数。
执行此操作的一种方法是在类中添加一个额外的类型参数。可以将其约束为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