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

如何让TypeScript识别类型检查?解决动态属性访问类型报错

解决TypeScript动态获取对象属性的类型收窄问题

你遇到的问题核心是TypeScript无法通过typeof判断来正确收窄自定义类的类型,同时也没有建立property参数与对象属性类型的关联关系,导致类型检查报错。下面先分析错误原因,再给出具体的解决方法。

错误原因解析

  1. TS2339错误:当进入else分支时,TypeScript依然认为obj[property]的类型是number | Color——因为typeof对自定义类实例返回的是"object",虽然你知道此时值是Color,但TS无法通过typeof的判断结果直接推导出这一点,所以不允许调用toArray方法。
  2. TS2322错误:当property为'color'时,obj[property]是Color类型,而函数返回类型定义为number | number[],Color与这两个类型都不兼容,因此报错。

解决方案

方案一:自定义类型守卫明确区分类型

通过instanceof判断是否为Color实例,并编写类型谓词让TypeScript识别类型:

class Color {
  r: number
  g: number
  b: number
  constructor(r: number, g: number, b: number) {
    this.r = r;
    this.g = g;
    this.b = b;
  }

  toArray() {
    return [this.r, this.g, this.b];
  }
}

interface MyObject {
  intensity: number,
  color: Color,
}

type ObjectProperty = 'intensity'|'color'

// 自定义类型守卫函数
function isColor(value: number | Color): value is Color {
  return value instanceof Color;
}

const myFunc = (obj: MyObject, property: ObjectProperty): number|number[] => {
  const value = obj[property];
  if (typeof value === 'number') {
    return value;
  } else if (isColor(value)) {
    return value.toArray();
  }
  // 处理理论上不可能出现的情况,避免TS报错
  throw new Error(`Invalid property type for ${property}`);
}

方案二:用泛型关联属性与返回类型

这种方法能让函数返回类型与传入的property严格对应,提供更精确的类型提示:

class Color {
  r: number
  g: number
  b: number
  constructor(r: number, g: number, b: number) {
    this.r = r;
    this.g = g;
    this.b = b;
  }

  toArray() {
    return [this.r, this.g, this.b];
  }
}

interface MyObject {
  intensity: number,
  color: Color,
}

type ObjectProperty = 'intensity'|'color'

// 定义属性到返回类型的映射
type PropertyReturnMap = {
  intensity: number;
  color: number[];
};

const myFunc = <K extends ObjectProperty>(obj: MyObject, property: K): PropertyReturnMap[K] => {
  const value = obj[property];
  if (property === 'intensity') {
    return value;
  } else {
    return value.toArray();
  }
}

// 使用示例:
const testObj: MyObject = {
  intensity: 0.7,
  color: new Color(255, 0, 0)
};
const intensity = myFunc(testObj, 'intensity'); // 类型自动推导为number
const colorArr = myFunc(testObj, 'color'); // 类型自动推导为number[]

方案三:用in操作符直接检查属性

通过检查toArray属性是否存在,让TypeScript自动收窄类型:

class Color {
  r: number
  g: number
  b: number
  constructor(r: number, g: number, b: number) {
    this.r = r;
    this.g = g;
    this.b = b;
  }

  toArray() {
    return [this.r, this.g, this.b];
  }
}

interface MyObject {
  intensity: number,
  color: Color,
}

type ObjectProperty = 'intensity'|'color'

const myFunc = (obj: MyObject, property: ObjectProperty): number|number[] => {
  const value = obj[property];
  if (typeof value === 'number') {
    return value;
  } else if ('toArray' in value) {
    return value.toArray();
  }
  throw new Error(`Unexpected property type for ${property}`);
}

总结

原来的代码无法通过typeof让TS识别Color类型,因为自定义类实例的typeof结果是"object",而非类本身的类型。上面三种方法都能解决这个问题,其中泛型方案的类型提示最精确,类型守卫方案适合需要复用类型判断的场景,in操作符方案则最简单直接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 13:58:11