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

如何为动态函数参数实现TypeScript自动补全?

TypeScript类型安全调用对象方法的解决方案

场景与问题背景

定义了如下只读对象:

const obj = {
    property1: {
        func: ({num1,num2,operation}:{num1: number, num2: number, operation: string}) => "p1"
    },
    property2: {
        func: ({obj}:{obj: {[key: string]: string}}) => "p2"
    }
} as const

需求是实现一个函数,通过传入属性名(如property1),调用对应属性下的func方法。

初始不安全实现

最初的版本使用any类型,完全失去TypeScript的类型校验和自动补全能力:

function getFuncFromObj(property: string, parameters: {[key:string]: any}): any {
  return obj[property]['func'](parameters)
}

getFuncFromObj("property1", {num1: 2, num2: 5, operation: "+"})

泛型版本的问题

尝试泛型版本后,虽然能实现自动补全,但调用时TypeScript抛出类型错误:

function getFuncFromObj<T extends keyof typeof obj, K extends Parameters<typeof obj[T]["func"]>[0]>(key: T,parameters: K): string {
    return obj[key]["func"](parameters)
}

getFuncFromObj("property1", {num1: 2, num2:5, operation: "+"})

错误信息:

TS2345: Argument of type '{ num1: number; num2: number; operation: string; } | { obj: { [key: string]: string; }; }' is not assignable to parameter of type '{ num1: number; num2: number; operation: string; } & { obj: { [key: string]: string; }; }'.        
  Type '{ num1: number; num2: number; operation: string; }' is not assignable to type '{ num1: number; num2: number; operation: string; } & { obj: { [key: string]: string; }; }'.
    Property 'obj' is missing in type '{ num1: number; num2: number; operation: string; }' but required in type '{ obj: { [key: string]: string; }; }'.

318     return obj[key]["func"](parameters)
                                ~~~~~~~~~~

问题根源:TypeScript无法跟踪泛型参数T和K的关联关系,会将parameters推断为所有可能参数的联合类型,但函数调用时要求参数满足所有func的参数(即交叉类型),导致类型不匹配。

正确实现方案

方案1:单泛型参数关联类型

直接通过单个泛型参数T绑定属性名与对应func的参数类型,让TypeScript精确推断参数:

function getFuncFromObj<T extends keyof typeof obj>(
  key: T,
  parameters: Parameters<typeof obj[T]["func"]>[0]
): ReturnType<typeof obj[T]["func"]> {
  return obj[key].func(parameters) as ReturnType<typeof obj[T]["func"]>;
}

方案2:预定义映射类型

先通过映射类型定义每个属性对应的参数类型,再在函数中使用:

// 预定义每个属性对应的func参数类型
type ObjFuncParams = {
  [K in keyof typeof obj]: Parameters<typeof obj[K]["func"]>[0];
};

function getFuncFromObj<T extends keyof ObjFuncParams>(
  key: T,
  parameters: ObjFuncParams[T]
): string {
  return obj[key].func(parameters);
}

验证效果

两种方案都能实现:

  • 自动补全属性名和对应参数
  • 严格的类型校验,参数不匹配时直接报错
// 合法调用,自动补全正常
getFuncFromObj("property1", { num1: 2, num2: 5, operation: "+" });
getFuncFromObj("property2", { obj: { name: "test" } });

// 非法调用,TypeScript直接报错
getFuncFromObj("property1", { obj: {} }); // 参数不符合property1的要求
getFuncFromObj("property1", { num1: 2, operation: "+" }); // 缺少num2参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:39:17