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

为何typeof检测number|null类型返回'object'?如何获取其完整类型?

如何获取TypeScript属性的声明类型(number|null)?

问题场景

可复现代码:

class MyObject{
    id: number|null = null
}

const a = new MyObject()
console.log(typeof a.id)

执行结果:

'object'

问题核心:已知typeof null返回object的原因,但想通过类似反射的方式获取该属性声明的number|null完整类型。

解决方案

TypeScript的类型系统是编译时生效的,编译后的JavaScript代码会完全擦除类型信息,所以直接通过运行时API(比如typeof)无法获取声明的类型。要实现这个需求,需要通过元数据注入的方式,在编译阶段把类型信息保留到运行时。

方法1:使用reflect-metadata(官方推荐的元数据方案)

  1. 先安装依赖:
npm install reflect-metadata
  1. 修改tsconfig.json,启用装饰器和元数据发射:
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}
  1. 编写代码:
import 'reflect-metadata';

class MyObject {
  // 空装饰器触发元数据收集(必须有装饰器才能让TS发射类型元数据)
  @(() => {})
  id: number|null = null;
}

const a = new MyObject();
// 获取属性的设计类型元数据
const typeConstructor = Reflect.getMetadata('design:type', a, 'id');
console.log(typeConstructor.name); // 输出 "Number"

注意:默认的design:type元数据只能识别单一构造函数类型,对于number|null这种联合类型,它只会返回Number(因为null没有构造函数)。如果需要精准获取number|null的完整声明,需要自定义元数据。

方法2:自定义装饰器存储完整类型信息

如果需要准确保留number|null这类联合类型的声明,可以自己写装饰器来存储类型字符串:

import 'reflect-metadata';

// 自定义装饰器,手动传入类型描述
function Type(type: string) {
  return (target: any, propName: string) => {
    Reflect.defineMetadata('custom:type', type, target, propName);
  };
}

class MyObject {
  @Type('number|null')
  id: number|null = null;
}

const a = new MyObject();
const declaredType = Reflect.getMetadata('custom:type', a, 'id');
console.log(declaredType); // 输出 "number|null"

这种方式完全可控,能精准存储你需要的类型信息,但需要手动维护装饰器的类型字符串和TS声明的一致性。

总结

TypeScript本身没有内置的运行时类型反射能力,必须通过编译时注入元数据的方式才能获取声明的类型信息。根据需求选择reflect-metadata的默认元数据,或者自定义装饰器来存储完整类型描述。

内容的提问来源于stack exchange,提问作者E. Williams

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:20:21