使用不同类型的每个键实例化泛型类型
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">
我有一个可用的 '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">