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

如何限制TypeScript回调函数参数禁止使用unknown类型

如何禁止TypeScript回调函数使用unknown类型参数并保留合法情况

现有代码:

const any = (any?: any): any => any;

export type Fn = (cb: (...args: (string | number)[]) => any) => any;

const Fn: Fn = any();

const t1 = Fn((x: unknown) => x); // 当前允许通过,需禁止
const t2 = Fn(<X>(x: X) => x); // 当前允许通过,需禁止

需求:禁止回调函数中使用unknown类型的参数,同时避免出现无约束的泛型参数。

已尝试但无效的方法:

  • 在tsconfig.json中设置strictFunctionTypes
  • 使用Exact工具类型
  • 在cb声明中使用泛型

应当被允许的合法情况:

const t3 = Fn((a: string, b: number) => {});
const t4 = Fn(() => {});
const t5 = Fn((x: string | number, y: string) => {});
const t6 = Fn(<X extends number>(x: X) => x);
const t7 = Fn(<X extends string, Y extends string>(x: X, y: Y) => x + y);

目前上述合法情况多数无法正常通过,该如何解决?


解决方案

通过约束回调函数的参数类型,结合TypeScript的泛型与条件类型,可以精准区分合法与非法情况,实现需求:

// 工具类型:仅保留 string | number 子集,排除 unknown
type AllowedParam<T> = T extends string | number ? T : never;

// 重新定义 Fn 类型,对每个参数做约束
export type Fn = <Args extends unknown[]>(
  cb: (...args: { [K in keyof Args]: AllowedParam<Args[K]> }) => any
) => any;

const any = (any?: any): any => any;
const Fn: Fn = any();

// 非法情况(触发报错)
const t1 = Fn((x: unknown) => x); // ❌ unknown 不属于允许类型
const t2 = Fn(<X>(x: X) => x); // ❌ 无约束泛型不满足条件

// 合法情况(正常通过)
const t3 = Fn((a: string, b: number) => {}); // ✅
const t4 = Fn(() => {}); // ✅
const t5 = Fn((x: string | number, y: string) => {}); // ✅
const t6 = Fn(<X extends number>(x: X) => x); // ✅
const t7 = Fn(<X extends string, Y extends string>(x: X, y: Y) => x + y); // ✅

原理说明

  1. AllowedParam工具类型:通过条件类型过滤掉unknown及非string | number的类型,仅保留合法参数类型。
  2. Fn泛型约束:捕获回调的参数列表,通过映射类型对每个参数逐一校验,确保符合AllowedParam的要求。
  3. 无约束泛型拦截:无约束的泛型X无法匹配AllowedParam,会返回never,导致参数类型不匹配触发错误。

注意:需确保tsconfig.json中启用strict: true(至少包含strictFunctionTypes),保证类型检查生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:22:43