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

如何在TypeScript中强制仅接受花括号形式的对象?

TypeScript 仅接受花括号形式对象的类型定义

要实现仅接受花括号键值对对象(排除数组、函数、类、类实例)的函数参数类型,可以利用TypeScript的条件类型和结构特征来区分不同对象类型,以下是几种可行方案:

方案1:基础排除(覆盖大部分场景)

通过排除数组和函数的标志性特征(迭代器、call方法),实现基础的过滤:

// 定义仅接受纯键值对对象的类型
type PlainObject = object & {
  // 排除数组:数组默认实现Symbol.iterator
  [Symbol.iterator]?: never;
  // 排除函数:函数默认拥有call方法
  call?: never;
};

function func(param: PlainObject) {}

// 测试用例
func({ hello: "world" }) // ✅ 正常生效
func([1,23,4])           // ❌ 报错(数组包含Symbol.iterator)
func(function() {})      // ❌ 报错(函数包含call方法)

class T {}
func(T)                  // ❌ 报错(类构造函数属于函数类型)
func(new T())            // ⚠️ 注意:空类实例会被允许,因为它没有上述特征

方案2:严格排除类实例

如果需要同时排除类实例,可以通过限制constructor为Object类型,区分自定义类实例和字面量对象:

type PlainObject = object & {
  [Symbol.iterator]?: never;
  call?: never;
  // 仅允许构造函数为Object的对象(字面量对象的constructor默认是Object)
  constructor?: typeof Object;
};

function func(param: PlainObject) {}

// 测试用例
func({ hello: "world" }) // ✅ 正常生效
func(new T())            // ❌ 报错(类实例的constructor是自定义类T)
func(Object.create(null)) // ❌ 报错(该对象没有constructor属性)

方案3:兼容无原型对象的严格方案

如果需要支持Object.create(null)创建的无原型对象,可以用条件类型优化,允许没有constructor的对象:

type PlainObject = object extends infer T
  ? T extends Array<any> | Function
    ? never // 排除数组和函数
    : T extends { constructor: infer C }
      ? C extends typeof Object
        ? T // 仅保留构造函数为Object的对象
        : never
      : T // 允许没有constructor的对象(如Object.create(null))
  : never;

function func(param: PlainObject) {}

// 测试用例
func({ hello: "world" }) // ✅ 正常生效
func(Object.create(null)) // ✅ 正常生效
func(new T())            // ❌ 报错
func([1,23,4])           // ❌ 报错

注意事项

TypeScript采用结构化类型系统,无法100%区分所有极端场景(比如手动修改了constructor的类实例),但上述方案已经能覆盖绝大多数日常开发中的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:20:18