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

如何在forEach方法中为类的赋值属性正确添加TypeScript类型?

问题解决:为Effect代码添加正确的TypeScript类型

报错核心原因:Object.keys(watchers)返回的类型是string[],但Effect实例的可赋值属性是_done、_fail(而非直接的done/fail方法),TypeScript无法确认遍历出的字符串键是否属于Effect的有效属性,因此抛出类型不兼容错误。

以下是两种可行的修复方案:

方案一:类型断言约束键类型

直接断言遍历的键为watchers的合法键,并将键名映射到Effect的私有属性(添加下划线前缀):

type TDone =  (res: string) => void;
type TFail =  (res: string) => void;

class Effect {
  _done?: TDone;
  _fail?: TFail;

  constructor({ done: _done, fail: _fail }: { done?: TDone, fail?: TFail } = {}) {
    this._done = _done;
    this._fail = _fail;
  }

  done() {
    return this._done?.('ok!')
  }

  fail() {
    return this._fail?.('fail!')
  }
}

const createEffect = (watchers : { done?: TDone, fail?: TFail }) => {
  const effect = new Effect();

  // 断言键为watchers的合法键,避免string类型的宽泛约束
  (Object.keys(watchers) as Array<keyof typeof watchers>).forEach((watcher) => {
    // 将done/fail映射到对应的私有属性_done/_fail
    effect[`_${watcher}` as keyof Effect] = watchers[watcher];
  })

  return effect;
}

const effect = createEffect({ done: () => console.log('done!') });

effect.fail();

方案二:泛型+类型映射优化严谨性

通过泛型约束输入参数,同时用类型映射明确私有属性的键对应关系:

type TDone =  (res: string) => void;
type TFail =  (res: string) => void;

// 定义watchers的类型
type Watchers = { done?: TDone, fail?: TFail };
// 映射watchers的键到Effect的私有属性键(比如done -> _done)
type EffectPrivateKeys = { [K in keyof Watchers]: `_${K}` }[keyof Watchers];

class Effect {
  _done?: TDone;
  _fail?: TFail;

  constructor({ done: _done, fail: _fail }: Partial<Watchers> = {}) {
    this._done = _done;
    this._fail = _fail;
  }

  done() {
    return this._done?.('ok!')
  }

  fail() {
    return this._fail?.('fail!')
  }
}

const createEffect = <T extends Partial<Watchers>>(watchers: T) => {
  const effect = new Effect();

  (Object.keys(watchers) as Array<keyof T>).forEach((watcher) => {
    const privateKey = `_${watcher}` as EffectPrivateKeys;
    effect[privateKey] = watchers[watcher];
  })

  return effect;
}

const effect = createEffect({ done: () => console.log('done!') });

effect.fail();

关键注意点

  • 原代码的误区是直接给effect[watcher]赋值,但done/fail是Effect的方法,而非可赋值属性,实际存储回调的是_done/_fail私有属性,必须做键名映射。
  • 使用类型断言是为了缩小Object.keys返回值的类型范围,让TypeScript确认遍历的键是合法的,而非任意字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:55:25