这个问题很难用语言解释,但用代码很容易解释:-)这就是我想要实现的目标( TS Playground )
enum ActionType {
Add = 'add',
Concat = 'concat'
};
interface AddActionPayload {
num1: number;
num2: number;
}
interface ConcatActionPayload {
str1: string;
str2: string;
}
interface AddAction {
type: ActionType.Add;
payload: AddActionPayload;
}
interface ConcatAction {
type: ActionType.Concat;
payload: ConcatActionPayload;
}
type Actions = AddAction | ConcatAction;
const payloads: Record<ActionType, Actions['payload']> = {
add: {
// accept only AddActionPayload
},
concat: {
// accept only ConcatActionPayload
}
}
知道如何实现这一目标吗?
最佳答案
Record<K, V>
utility type是 mapped type其中键和值类型完全不相关。其形式为type Record<K, V> = {[P in K]: V}
,其中每个键的键类型 P
(迭代 K
成员的 union )对相应的值类型没有任何影响,即 V
无论。所以你会得到你不喜欢的行为:
type Oops = Record<ActionType, Actions['payload']>;
/* type Oops = {
add: AddActionPayload | ConcatActionPayload;
concat: AddActionPayload | ConcatActionPayload;
} */
相反,您应该编写一个映射类型,其中值显式依赖于键。因为你有一个 Actions
union代表你想要的信息,最简单的就是直接映射到Actions
使用key remapping在映射类型中提取键类型和值类型。
看起来像这样:
type Payloads = { [T in Actions as T['type']]: T['payload'] };
/* type Payloads = {
add: AddActionPayload;
concat: ConcatActionPayload;
} */
这就是你想要的行为:
const payloads: Payloads = {
add: { num1: 1, num2: 2 },
concat: { str1: "a", str2: "b" }
}; // okay
const badPayloads: Payloads = {
add: { str1: "a", str2: "b" },
concat: { num1: 1, nume2: 2 }
}; // error!
关于typescript - 接口(interface)与类型字段的联合,创建一个类型为 : type - specific attribute of that types interface 的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74321882/