如何为embind的extend方法编写正确的TypeScript类型定义
问题描述
为embind的extend功能编写类型定义时遇到了无法解决的问题,现有代码如下:
export declare class Deletable { public delete(): void; } type Constructor<T> = new (...args: any[]) => T; export declare class Extendable extends Deletable { public static extend<T extends Constructor<T>>(name: string, o: unknown): new (...args: ConstructorParameters<T>) => T; public static implement<T>(o: object): T; } class Lexer extends Extendable { public constructor(i?: number) { super(); } } const WhiteboxLexerTrampoline = Lexer.extend<Lexer>("Lexer", { });
调用Lexer.extend<Lexer>()时触发如下错误:
Type 'Lexer' does not satisfy the constraint 'Constructor'.
Type 'Lexer' provides no match for the signature 'new (...args: any[]): Lexer'.(2344)
补充说明:extend返回的类将用于派生业务类,示例如下:
export default class WhiteboxLexer extends WhiteboxLexerTrampoline { // 词法分析器的具体实现 }
解决方案
错误根源在于extend方法的泛型约束逻辑错误:T extends Constructor<T>要求T本身是构造函数类型,但你传入的Lexer是类实例类型,并非构造函数类型,两者不匹配导致报错。
修正后的类型定义
export declare class Deletable { public delete(): void; } // 定义通用构造函数类型:接受任意参数,返回T类型实例 type Constructor<T = {}> = new (...args: any[]) => T; export declare class Extendable extends Deletable { // 泛型T约束为构造函数类型,返回同类型的构造函数 public static extend<T extends Constructor>(name: string, o: unknown): T; public static implement<T>(o: object): T; } class Lexer extends Extendable { public constructor(i?: number) { super(); } } // 无需手动指定泛型,TypeScript会自动推导构造函数类型 const WhiteboxLexerTrampoline = Lexer.extend("Lexer", { }); // 派生类可直接继承返回的构造函数 export default class WhiteboxLexer extends WhiteboxLexerTrampoline { // 实现自定义逻辑 }
更精确的类型约束(可选)
如果需要严格匹配原类的构造函数参数和实例类型,可以进一步优化extend的返回类型:
export declare class Extendable extends Deletable { public static extend<T extends Constructor>( name: string, o: unknown ): new (...args: ConstructorParameters<T>) => InstanceType<T>; }
这样extend返回的构造函数会完全继承原类T的参数签名和实例类型,类型安全性更高。
核心问题就是混淆了类实例类型和构造函数类型:Lexer代表的是类实例的类型,而Constructor<T>是创建实例的构造函数类型,之前的泛型约束错误地将两者绑定,导致TypeScript无法解析匹配关系。
内容的提问来源于stack exchange,提问作者Mike Lischke
相关产品推荐
相关产品推荐

