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

如何用TypeScript实现调用String原型方法的通用函数?

在TypeScript中实现针对String原型方法的类型安全调用函数

问题分析

你遇到的报错核心原因是:当T为Callable<String>的联合类型时,String[T]会成为所有符合条件的String方法类型的联合。TypeScript对联合类型的调用有严格限制——只有当联合中所有成员的调用签名完全兼容时,才允许直接调用。但String的单参数方法签名并不统一(比如slice支持可选参数,charAt仅接受number,indexOf接受string/number等),因此TS判定该联合类型不可调用。

而你用泛型Q传入具体String实例的方案能正常运行,是因为此时Q被推断为具体的String类型,T会被推断为单个具体的方法键(而非联合类型),Q[T]对应单个方法类型,不存在签名兼容问题。

解决方案

优化后的类型安全实现

我们可以保留泛型约束,结合TypeScript内置的Parameters和ReturnType类型,再通过类型断言绕过联合类型的调用限制(类型约束已确保参数与方法匹配):

// 生成所有接收至少一个参数的String方法键的联合类型
type CallableWithOneArg<R> = keyof {
  [K in keyof R]: R[K] extends (arg: any, ...rest: any[]) => any ? K : never
}[keyof R];

function callFunction<T extends CallableWithOneArg<String>>(
  key: T,
  param: Parameters<String[T]>[0]
): ReturnType<String[T]> {
  const importantString = 'password123';
  // 类型断言:告诉TS当前方法可接收对应参数并返回正确类型
  return (importantString[key] as (arg: Parameters<String[T]>[0]) => ReturnType<String[T]>)(param);
}

测试验证

callFunction('slice', 8); // 返回类型string,结果为'123'
callFunction('charAt', 5); // 返回类型string,结果为'3'
callFunction('indexOf', 'word'); // 返回类型number,结果为-1
callFunction('charAt', '5'); // TS报错:参数类型string不匹配charAt要求的number

替代方案:利用泛型推断具体方法

如果不想使用类型断言,也可以通过将固定字符串作为泛型参数传入的方式,让TS自动推断具体方法类型:

function callFunction<const S extends string, T extends CallableWithOneArg<String>>(
  str: S,
  key: T,
  param: Parameters<String[T]>[0]
): ReturnType<String[T]> {
  return str[key](param as Parameters<String[T]>[0]);
}

// 调用时无需类型转换
callFunction('password123', 'slice', 8);

额外提示

  • 无需自行实现FirstArgument和ReturnType,TypeScript已内置Parameters<T>[0](获取第一个参数类型)和ReturnType<T>(获取返回类型)工具类型。
  • 若想严格限制仅接收恰好一个参数的方法,可修改CallableWithOneArg的约束:
    type CallableWithExactOneArg<R> = keyof {
      [K in keyof R]: R[K] extends (arg: infer _) => any ? K : never
    }[keyof R];
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:55:20