TypeScript动态选属性时出现“This expression is not constructable”错误求助
问题解决:动态选择区块链网络时TransactionListener构造报错
问题原因
当前selectNetwork函数返回的是EvmChains | Bitcoin | Solana的联合类型,虽然三个模块都包含services.TransactionListener,但TypeScript检测到它们的构造函数签名存在不兼容差异(比如参数类型、内部实现不同),因此直接实例化时会抛出类型不兼容错误。
解决方案
方案1:类型断言(快速临时解决)
在实例化时通过类型断言明确告知TypeScript当前构造函数的可用签名:
import { selectNetwork, Keys } from './multiplechain' const network = selectNetwork(data.providerConfig.code as Keys) const provider = new network.Provider(data.providerConfig as any) // 添加类型断言跳过联合类型检查 const listener = new (network.services.TransactionListener as new (type: string) => any)('COIN')
方案2:公共接口约束(规范类型安全方案)
定义统一接口约束所有区块链模块的结构,让TypeScript明确识别各模块的公共属性:
import * as Solana from '@multiplechain/solana/node' import * as Bitcoin from '@multiplechain/bitcoin/node' import * as EvmChains from '@multiplechain/evm-chains/node' // 定义TransactionListener的公共构造接口(可根据实际参数调整) interface TransactionListenerConstructor { new (type: 'COIN' | 'TOKEN'): unknown; } // 定义区块链模块的公共结构 interface BlockchainNetwork { Provider: new (config: any) => unknown; services: { TransactionListener: TransactionListenerConstructor; }; types: { TransactionTypeEnum: { COIN: string; TOKEN: string; }; }; } export enum Type { COIN = Solana.types.TransactionTypeEnum.COIN, TOKEN = Solana.types.TransactionTypeEnum.TOKEN, } // 断言各模块符合公共接口 const networks: Record<Keys, BlockchainNetwork> = { evmchains: EvmChains as BlockchainNetwork, bitcoin: Bitcoin as BlockchainNetwork, solana: Solana as BlockchainNetwork, } export type Keys = keyof typeof networks export const selectNetwork = (key: Keys): BlockchainNetwork => networks[key]
修改后selectNetwork返回统一的BlockchainNetwork类型,TypeScript可正确识别构造签名,直接实例化不会报错。
方案3:泛型函数(保留模块具体类型)
通过泛型让TypeScript推断出具体模块的类型,避免联合类型的兼容性问题:
// 修改selectNetwork为泛型函数 export const selectNetwork = <K extends Keys>(key: K): typeof networks[K] => networks[key]
调用时指定泛型参数:
import { selectNetwork, Keys } from './multiplechain' const code = data.providerConfig.code as Keys // 指定泛型参数让TypeScript推断具体模块类型 const network = selectNetwork<typeof code>(code) const provider = new network.Provider(data.providerConfig as any) const listener = new network.services.TransactionListener('COIN')
这种方式既能保留各模块的具体类型信息,又能解决联合类型的构造兼容问题。
内容的提问来源于stack exchange,提问作者BeycanDeveloper
相关产品推荐
相关产品推荐

