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

如何解决TS中OmitProperties提取类属性时误排除any类型属性问题

问题描述

实现从类中提取全部属性生成对应类型的功能时,借助ts-essential库提供的OmitProperties工具类型,定义type GetProperties<T> = OmitProperties<T, Function>用于剔除类的方法属性。实际测试发现该写法不仅会移除类方法,还会将所有标注为any类型的属性一并排除。

测试代码如下:

type GetProperties<T> = OmitProperties<T, Function>

class Foo {
    foo: string = '';
    bar: any | null = null;
}

export type FooProperties = GetProperties<Foo>; // 最终仅得到类型{ foo: string; },缺失bar属性
问题根因

OmitProperties内部通过类型兼容性判断过滤匹配目标类型的属性,而TypeScript中any是顶层兼容类型,会和所有类型(包括Function)判定为兼容,因此any类型的属性会被误判为方法属性,被错误过滤。

改进实现

通过自定义映射类型实现属性提取,单独处理any类型的边界判断,避免any的全局兼容特性干扰过滤逻辑:

// 辅助类型:精准判断类型是否为any,无其他类型误判
type IsAny<T> = 0 extends (1 & T) ? true : false;

type GetClassProperties<T> = {
  [K in keyof T as 
    IsAny<T[K]> extends true
      ? K // any类型属性直接保留
      : T[K] extends Function
        ? never // 非any的函数类型属性过滤
        : K // 其余普通属性保留
  ]: T[K]
};

实现逻辑说明:

  • 利用any和任意类型交叉结果仍为any的特性,通过IsAny精准识别any类型属性,不会和其他类型产生混淆
  • 遍历类的所有键做条件判断:any类型属性直接保留,函数类型(类方法)过滤,其余普通属性全部保留
  • 支持保留any | null、any | undefined等包含any的联合类型属性
验证效果

使用改进后的类型做测试:

class Foo {
    foo: string = '';
    bar: any | null = null;
    sayHello() {} // 类方法
    count: number = 0;
    rawConfig: any = {};
}

export type FooProperties = GetClassProperties<Foo>;
// 最终得到类型:{ foo: string; bar: any | null; count: number; rawConfig: any }
// 所有非方法属性完整保留,类方法被正确剔除

注意事项:

  • 涉及类型兼容性判断的工具类型,必须单独处理any类型的边界情况,否则会因any兼容所有类型的特性出现逻辑错误
  • 提取类属性的场景不建议直接使用通用的OmitProperties实现,通用工具未针对类场景的any属性做特殊适配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:15:46