使用不同类型的每个键实例化泛型类型

Instantiate a generic type with every key of a different type

我有一个可用的 'solution',但它非常丑陋,我想知道是否有更干净的。我编写的代码大致如下,这实现了我的目标,即让打字稿正确推断 switch 语句的每个分支中 value 的类型。

type Foo = {
  key1: string
  key2: number
  key3: {message: string}
}

type FooProperty<Key extends keyof Foo> = {
  key: Key,
  value: Foo[Key],
}

type FooPropertyData = FooProperty<'key1'> | FooProperty<'key2'> | FooProperty<'key3'>

const func = (change: FooPropertyData) => {
  switch (change.key) {
    case "key1": {
      return change.value.toUpperCase()
    }
    case "key2": {
      return change.value * 8
    }
    case "key3": {
      return change.value.message
    }
  }
}

然而,这需要您手动将 Foo 的每个键添加到 FooPropertyData 类型。这显然不理想。我的第一个想法是做类似的事情:

type FooPropertyData = FooProperty<keyof Foo>

但这会失去类型安全性。有更好的方法吗?

如果标题有误导性,我深表歉意,我是泛型类型的新手,不确定如何最好地表达它。

解决方案是让 TypeScript 分别使用 keyof Foo 的每个组成部分:

type FooPropertyData<T extends keyof Foo = keyof Foo> = T extends T ? FooProperty<T> : never;

这种现象可以通过以下方式证明:

type All<T> = Set<T>;

type Each<T> = T extends T ? Set<T> : never;

type AllIn = All<"1" | "2">; // Set<"1" | "2">

type EachIn = Each<"1" | "2">; // Set<"1"> | Set<"2">

Playground