You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 16:45:17