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

TypeScript动态调用类方法:类型联合兼容问题修复求助

TypeScript动态调用不同参数类方法的类型问题

需求:在TypeScript中动态调用名称不同、参数接口各异的类方法,要求避免使用any类型和if分支。当前代码在常量定义调用规则时可正常运行,但接收Input联合类型参数的函数内无法工作,存在类型联合相关问题。

原代码

// 完全不同的接口,字段各异
interface A {
    foo: boolean;
}

interface B {
    bar: string;
    baz: number;
}

// 处理数据的操作类,每个方法对应严格类型的参数
class Operator {
    public processA(obj: A) {
        console.log('create');
    }

    public processB(obj: B) {
        console.log('edit');
    }
}

// Operator中所有操作,以及动态调用的输入集合
type Operations = 'processA' | 'processB';

type InputA = {
    operation: 'processA',
    obj: A;
}

type InputB = {
    operation: 'processB',
    obj: B;
}

type Input = InputA | InputB;

// 这段代码可正常运行
const action: Input = { operation: 'processB', obj: { bar: 'abc', baz: 1 } }; // 具体操作实例
const operator = new Operator();
operator[action.operation](action.obj); // 对具体action变量可正常调用

// 这段代码无法运行
function fixHerePlease(action: Input) {
    const operator = new Operator();
    operator[action.operation](action.obj); // 以action为参数时无法工作
}

错误信息(翻译后)

参数类型“A | B”无法赋值给类型“B & A”。类型“A”无法赋值给类型“B & A”。类型“A”缺少类型“B”中的以下属性:bar、baz

解决方案

核心问题是TypeScript无法自动关联联合类型中operation和obj的对应关系。我们可以通过泛型+映射类型让TypeScript正确推断类型关联,无需any或if分支:

// 完全不同的接口,字段各异
interface A {
    foo: boolean;
}

interface B {
    bar: string;
    baz: number;
}

// 处理数据的操作类,每个方法对应严格类型的参数
class Operator {
    public processA(obj: A) {
        console.log('create');
    }

    public processB(obj: B) {
        console.log('edit');
    }
}

// 自动提取Operator方法的参数类型映射
type OperatorMethods = typeof Operator.prototype;
type OperationParamMap = {
    [K in keyof OperatorMethods]: Parameters<OperatorMethods[K]>[0];
};

// 定义带泛型的Input类型,确保operation和obj的类型关联
type Input<K extends keyof OperationParamMap = keyof OperationParamMap> = {
    operation: K;
    obj: OperationParamMap[K];
};

// 这段代码可正常运行
const action: Input = { operation: 'processB', obj: { bar: 'abc', baz: 1 } };
const operator = new Operator();
operator[action.operation](action.obj);

// 修复后的函数,可正常工作
function fixHerePlease<K extends keyof OperationParamMap>(action: Input<K>) {
    const operator = new Operator();
    operator[action.operation](action.obj);
}

说明

  1. OperationParamMap通过映射类型自动提取Operator类所有方法的第一个参数类型,无需手动维护操作与参数的对应关系
  2. 泛型Input<K>确保operation的类型与obj的类型严格绑定
  3. 函数fixHerePlease使用泛型K,让TypeScript能根据传入的action推断出对应的方法和参数类型,完全类型安全

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:05:27