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

TypeScript类重构:如何定义对应类属性的方法参数类型

重构Card类的重复Getter逻辑,实现类型安全的通用方法

嘿,我明白你想把重复的懒加载逻辑提取成通用方法,还想保证类型安全的需求!TypeScript的泛型和keyof关键字刚好能完美解决这个问题,咱们一步步来重构:

首先,核心目标是让通用方法既能正确识别类的属性,又能匹配属性和getter的类型,避免出现any导致的类型丢失。

步骤1:定义带泛型的Getter类型

先把FieldValueGetter改成带返回值泛型的类型,这样能和目标属性的类型绑定起来:

type FieldValueGetter<V> = (data: Data, user: User) => V;

步骤2:实现类型安全的getFieldValue方法

用keyof Card约束属性名的范围,再通过泛型T关联属性的类型,让TypeScript自动帮我们做类型检查:

private getFieldValue<T extends keyof Card>(
  getter: FieldValueGetter<Card[T]>,
  fieldName: T
): Card[T] {
  if (!this[fieldName]) {
    this[fieldName] = getter(this.data, this.user);
  }
  return this[fieldName];
}
  • T extends keyof Card:确保fieldName是Card类的有效属性名,彻底避免拼写错误。
  • FieldValueGetter<Card[T]>:强制getter的返回值类型必须和目标属性的类型完全匹配,比如给nameVal(string类型)传的getter必须返回string。
  • 返回值Card[T]:让调用方能直接拿到正确的属性类型,不需要额外的类型断言。

步骤3:简化原有Getter

现在原来的name和address getter可以直接调用通用方法,代码瞬间简洁很多:

get name(): string {
  return this.getFieldValue(name_getter, 'nameVal');
}

get address(): string[] {
  return this.getFieldValue(address_getter, 'addressVal');
}

完整重构后的代码

// 先补充你的Data和User类型定义(根据实际情况修改)
type Data = {
  firstName: string;
  street: string;
  city: string;
};

type User = {
  lastName: string;
  country: string;
};

type FieldValueGetter<V> = (data: Data, user: User) => V;

class Card {
  protected readonly data: Data;
  protected readonly user: User;
  nameVal: string;
  addressVal: string[];

  constructor(raw_data: Data, user: User) {
    this.data = raw_data;
    this.user = user;
  }

  private getFieldValue<T extends keyof Card>(
    getter: FieldValueGetter<Card[T]>,
    fieldName: T
  ): Card[T] {
    if (!this[fieldName]) {
      this[fieldName] = getter(this.data, this.user);
    }
    return this[fieldName];
  }

  get name(): string {
    return this.getFieldValue(name_getter, 'nameVal');
  }

  get address(): string[] {
    return this.getFieldValue(address_getter, 'addressVal');
  }
}

// 示例getter函数(替换成你自己的业务逻辑)
function name_getter(data: Data, user: User): string {
  return `${data.firstName} ${user.lastName}`;
}

function address_getter(data: Data, user: User): string[] {
  return [data.street, data.city, user.country];
}

额外小提示

  • 把getFieldValue设为private是因为它是内部复用的逻辑,不需要对外暴露,符合封装原则。
  • 这种方式完全保留了类型安全:如果不小心给nameVal传了一个返回number的getter,TypeScript会直接抛出错误,提前规避运行时的类型问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 19:03:14