TypeScript中如何正确为实现IUserStore的类应用@asyncStore装饰器?
解决TypeScript装饰器扩展类时的接口实现错误
这个问题的核心在于TypeScript在装饰器应用前就会校验原始类是否符合接口要求,而你的UserStore原始类本身并没有isLoading属性——虽然装饰器会动态给它添加,但TypeScript的静态类型检查看不到这一点,所以抛出了TS2420错误。
下面是两种可行的解决方案:
方案1:完善装饰器的类型定义,让TypeScript识别装饰器会补充接口属性
我们可以给装饰器添加泛型类型声明,明确它会接收一个类,并返回一个实现了IAsyncStore接口的子类,这样TypeScript就能正确推断出装饰后的类符合IUserStore要求:
// Types interface IAsyncStore { isLoading: boolean; } interface IUserStore extends IAsyncStore {} // AsyncStore.ts // 给装饰器添加泛型类型,确保返回的类实现IAsyncStore function asyncStore<T extends new (...args: any[]) => {}>(constructor: T): T & new (...args: any[]) => IAsyncStore { class AsyncStore extends constructor implements IAsyncStore { private loading: boolean = false; public get isLoading(): boolean { return this.loading; } } return AsyncStore as T & new (...args: any[]) => IAsyncStore; } // UserStore.ts @asyncStore class UserStore implements IUserStore { // 现在TypeScript会知道装饰器会补充isLoading属性,无需手动实现 }
这里的关键是T & new (...args: any[]) => IAsyncStore——它告诉TypeScript,装饰器返回的类既是原始类T的类型,同时也实现了IAsyncStore接口。
方案2:在原始类中声明装饰器提供的属性
如果你不想修改装饰器的类型,也可以在UserStore中用declare关键字声明isLoading属性,告诉TypeScript这个属性会由装饰器动态添加,无需在原始类中实现:
// UserStore.ts @asyncStore class UserStore implements IUserStore { // 声明isLoading属性由装饰器提供 declare isLoading: boolean; }
这个方法更简洁,适合快速解决问题,但缺点是需要手动维护这些声明,当装饰器添加的属性变化时,要同步更新这里的声明。
两种方案都能解决你的类型校验问题,你可以根据项目的复杂度选择合适的方式。
内容的提问来源于stack exchange,提问作者Sander Vispoel
相关产品推荐
相关产品推荐

