TypeScript构造函数传类参数报无构造签名如何正确定义类型
报错原因
两次代码报错的核心原因是构造函数参数的类型标注不符合逻辑:你把参数类型标注为IFileHandler实例类型,但代码中对该参数执行了new实例化操作,TS识别到IFileHandler接口没有定义构造签名,因此抛出错误。
另外原写法本身也没有完全遵循依赖抽象的原则:如果在类内部直接实例化传入的参数,依然耦合了实例创建逻辑,没有完全解耦抽象与具体实现。
正确实现方案
方案1:传入已实例化对象(推荐,完全符合依赖倒置原则)
这种写法下XmlToJson完全依赖抽象接口,不需要关心IFileHandler的具体实现、也不需要处理实例化逻辑,只需要接收符合接口规范的实例即可,扩展性最强:
interface IFileHandler { getFiles (): string[] } class FileHandler implements IFileHandler { getFiles () { return ['hello', 'world']; } } class XmlToJson { private _fileHandler: IFileHandler; // 构造函数直接接收IFileHandler类型的实例 constructor (fileHandler: IFileHandler) { this._fileHandler = fileHandler; } run() { return this._fileHandler.getFiles() } } // 外部完成实例化再传入,后续替换实现只需要修改传入的实例即可 const fileHandler = new FileHandler() const xmlToJson = new XmlToJson(fileHandler) console.log(xmlToJson.run()) // 输出 ['hello', 'world']
方案2:传入类构造器,在内部完成实例化
如果业务场景要求必须把类作为参数传入、在XmlToJson内部做实例化,需要将参数类型标注为「符合IFileHandler返回值的构造函数类型」,而不是直接标注为IFileHandler:
interface IFileHandler { getFiles (): string[] } class FileHandler implements IFileHandler { getFiles () { return ['hello', 'world']; } } // 定义构造器类型:无参构造、返回IFileHandler实例的类 type IFileHandlerConstructor = new () => IFileHandler class XmlToJson { private _fileHandler: IFileHandler; // 构造函数接收可实例化的类构造器 constructor (FileHandlerCtor: IFileHandlerConstructor) { this._fileHandler = new FileHandlerCtor(); } run() { return this._fileHandler.getFiles() } } // 直接传入类本身即可,不需要提前实例化 const xmlToJson = new XmlToJson(FileHandler) console.log(xmlToJson.run()) // 输出 ['hello', 'world']
如果具体的FileHandler实现类构造函数需要传入参数,只需要同步调整构造器类型的签名即可,比如构造需要传入路径字符串,就把类型改为
new (filePath: string) => IFileHandler。
内容的提问来源于stack exchange,提问作者stackcen
相关产品推荐
相关产品推荐

