【问题标题】:How to make this TypeScript code DRY (Don't Repeat Yourself)?如何使这个 TypeScript 代码干燥(不要重复自己)?
【发布时间】:2022-01-21 18:02:40
【问题描述】:

下面是从我正在开发的 Redux 减速器中提取的一些 TypeScript 代码的片段。它有效,但它肯定是冗长的。必须有更好的方法来做到这一点,对吧?

  switch (iterationNum) {
    case 1:
      state.iteration1Result = action.payload;
      break;
    case 2:
      state.iteration2Result = action.payload;
      break;
    case 3:
      state.iteration3Result = action.payload;
      break;
    case 4:
      state.iteration4Result = action.payload;
      break;
    case 5:
      state.iteration5Result = action.payload;
      break;
    case 6:
      state.iteration6Result = action.payload;
      break;
    case 7:
      state.iteration7Result = action.payload;
      break;
    case 8:
      state.iteration8Result = action.payload;
      break;
  }

下面是状态的定义:

interface InitialState {
  iteration1Result: IterationResult;
  iteration2Result: IterationResult;
  iteration3Result: IterationResult;
  ..., etc.
}

我天真地希望我能做这样的事情

state[`iteration${iterationNum}result`] = action.payload;

但我收到此错误:

Element implicitly has an 'any' type because expression of type '`iteration${number}Result`' can't be used to index type 'WritableDraft<TestStartActivity>'.ts(7053)

【问题讨论】:

  • 你不应该有 iteration1Result 等属性开始。请改用数组。
  • 我的数据科学家正在请求这些字段名称。这被踢到 JSON。

标签: typescript redux typescript-typings


【解决方案1】:

不要使用switch,使用iterationNum 使用括号表示法来提出要分配的属性。使用模板文字构造属性名称,以便 TypeScript 可以正确解释它。

假设iterationNum1 | 2 | 3 | 4 | 5 | 6 | 7 | 8,你可以这样做

state[`iteration${iterationNum}Result`] = action.payload;

如果您必须首先缩小 iterationNum... 在 JavaScript 中,您将使用 .includes 进行检查,但那是 not really possible in a neat way in TypeScript(由于可以说是一个错误的行为)。要么做

if (iterationNum === 1 || iterationNum === 2 // etc

const nums = [1, 2, 3] as const; // etc
type Num = (typeof nums)[number];
if (nums.includes(iterationNum as Num)) {
    state[`iteration${iterationNum as Num}Result`] = action.payload;
}

【讨论】:

  • 补充,也可以使用Record&lt;`iteration${T}Result`, IterationResult&gt;创建InitialState类型,其中T等于1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
  • state[iteration${iterationNum as Num}Result] 产生的错误类似于我在问题中给出的错误:ts(7053)
  • @JayKoutavas 听起来您的Numnumber,而不是1 | 2 | 3 等。在我的回答中使用该方法,以便Num 将别名为联合而不是number
  • @enzo,你能扩展你的答案吗?使用这种方法,InitialState 的定义如何?
  • @JayKoutavas 嗯,从 TypeScript 的官方 IDE 中可以看出,似乎没有出现这样的问题……
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多