我正在尝试使用映射类型在映射中使用联合类型时提供更多的类型安全性。使用属性类型时,似乎没有办法在键/值之间提供类型安全性(例如['value']
( 作为键的类型 (K
(。
我想避免手动创建一个独特的模型来允许这一点。
法典:
interface IAction { value: string; }
type ActionMapper<A extends IAction> = {
[K in A['value']]: A;
}
interface IActionOne { value: 'action_one' }
interface IActionTwo { value: 'action_two' }
type Actions = IActionOne | IActionTwo;
const reducerMap: ActionMapper<Actions> = {
action_one: { value: 'action_one' },
action_two: { value: 'action_one' }, // expecting this line to fail
}
我已经评论了我预计会失败的行。
我觉得我应该能够利用键(K in
(来提供正确的类型作为值。但是,我目前使用A
,它提供了value
类型为string
的IAction
实现 - 我想避免这种情况。
这在当前版本的 TypeScript 中可能吗?
是的,可以做你想做的事。
如您所注意到的,您的问题是ActionMapper<A>
的属性值始终A
。 对于Actions
来说,这是一种联合类型。 您真正想做的是从A
中提取与每个键K
的{value: K}
匹配的成分。 幸运的是,有一个名为Extract
的预定义条件类型可以为您执行此操作。 让我们重新定义ActionMapper<A>
:
type ActionMapper<A extends IAction> = {
[K in A['value']]: Extract<A, {value: K}>;
}
现在我们将重试:
const reducerMap: ActionMapper<Actions> = {
action_one: { value: 'action_one' },
action_two: { value: 'action_one' }, // error!
// Type '"action_one"' is not assignable to type '"action_two"'.
}
你会得到你预期的错误。 希望有帮助。 祝你好运!