打字稿对象字段键一般

Typescript object fields keys generically

我有一个数据结构,其中包含各种不同类型的可选字段,必须单独获取并设置格式。格式化函数采用具体值。

我尝试做类似下面的最小工作示例的操作,但是 Property 'value' does not exist on type 'Data[P]'.

出现错误

我明白为什么会出现这个问题,但我想解决这个问题。我的快速破解方法是将 data[idx][key] 转换为 Optional<T>,但这可以在没有类型转换的情况下完成吗?

// In my code this is more complex, a simple `T | undefined` doesn't work.
type Optional<T> = { kind: 'none' } | { kind: 'value', value: T};

interface Data {
  name: Optional<string>;
  id: Optional<number>;
}

function computeIndex(): number {
  // Some logic here
  return 0;
}

// Format field `key` of `data` using `formatter`.
// Use default `def` if the value is `none`.
function printField<
  P extends keyof Data,
  T extends Data[P] extends Optional<infer V> ? V : never
>(data: Data[], key: P, formatter: (val: T) => string, def: T): string {
  const idx = computeIndex();

  const field = data[idx][key];

  switch (field.kind) {
    case 'none':
      return formatter(def);

    case 'value':
      return formatter(field.value);
  }
}

我认为目前没有免铸解决方案。

最终,TS 似乎无法从 field 声明中的 Optional<string> | Optional<number> 推断出 Optional<string | number>,因此我们以 Optional<T> 的形式给予它额外的推动演员.

这是黑客攻击吗?如果您将其视为绕过 TS 检查器的推理限制,也许可以。如果它打开了输入错误值的大门,或者如果结果没有达到预期的效果,我会同意这是一个 hack

但最终结果与“非黑客”解决方案一样有效,因为它正确地对给定 keyformatter 进行了类型检查。而且我不明白转换如何导致错误类型的值通过。