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

如何定义仅接受单个对象参数的TypeScript函数类型?

如何定义仅接受单个对象类型参数的TypeScript函数类型?

要实现仅允许单个对象类型参数的函数赋值给目标类型,核心难点在于函数参数的逆变特性:宽泛参数类型的函数(如(arg: object) => any)无法接受更具体参数类型的函数(如(arg: {str: string}) => {}),因为后者只能处理特定结构的对象,不满足前者“能处理任意对象”的要求。

以下是可行的实现方案:

方案一:泛型辅助函数+条件类型约束

这是最安全且符合需求的方式,通过条件类型检查函数参数是否为对象类型,辅助函数负责约束赋值过程:

// 定义类型工具:判断函数的唯一参数是否为对象类型
type ObjectParamFunction<F> = 
  F extends (arg: infer U) => any 
    ? U extends object 
      ? F 
      : never 
    : never;

// 辅助函数,用于约束赋值操作
const assignObjectParamFun = <F>(fn: ObjectParamFunction<F>): F => fn;

// 使用示例
let fun = assignObjectParamFun((arg: object) => {});                 // ✅ 合法
fun = assignObjectParamFun((arg: {}) => {});                     // ✅ 合法
fun = assignObjectParamFun((arg: {str: string}) => {});          // ✅ 合法
fun = assignObjectParamFun((arg: {obj: {}, num: number}) => {}); // ✅ 合法
fun = assignObjectParamFun((arg: number) => {});                 // ❌ 错误:非对象参数的函数无法通过约束

方案二:直接定义泛型类型(需类型断言)

如果不想使用辅助函数,可直接定义泛型类型,但赋值时需要手动添加类型断言(安全性略低):

type RestrictToObjectParam = <U extends object>(arg: U) => any;

let fun: RestrictToObjectParam;
fun = ((arg: object) => {}) as RestrictToObjectParam;                 // ✅ 合法
fun = ((arg: {}) => {}) as RestrictToObjectParam;                     // ✅ 合法
fun = ((arg: {str: string}) => {}) as RestrictToObjectParam;          // ✅ 合法
fun = ((arg: {obj: {}, num: number}) => {}) as RestrictToObjectParam; // ✅ 合法
fun = ((arg: number) => {}) as RestrictToObjectParam;                 // ❌ 错误:类型转换不兼容

为什么之前的尝试无效?

  • (arg: object) => any:受逆变特性限制,仅接受能处理任意对象的函数,具体结构的对象参数函数无法赋值。
  • <T extends object>(arg: T) => any:TypeScript会将泛型T推断为最宽泛的object类型,本质等价于(arg: object) => any,同样无法兼容具体对象参数的函数。
  • T extends object ? (arg: T) => void : never:条件类型最终会被解析为(arg: object) => void,依然受逆变特性约束,无法满足需求。

内容的提问来源于stack exchange,提问作者D. Johnson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 13:17:07