想象以下简化的设置:
import { Action, AnyAction } from 'redux'; // interface Action<Type> { type: Type } and type AnyAction = Action<any>
export type FilterActionByType<
A extends AnyAction,
ActionType extends string
> = A['type'] extends ActionType ? A : never;
type ActionUnion = Action<'count/get'> | Action<'count/set'>;
type CountGetAction = FilterActionByType<ActionUnion, 'count/get'>;
// expected: Action<'count/get'>
// received: never
有没有办法做到这一点?(打字稿3.7是一个选项)
你想FilterActionByType<A, T>
采取联合类型A
,并分头行事每个成员,然后把所有的结果,并在一个新的联盟团结他们......你想办法FilterActionByType<A, T>
到分布在工会(至少A
)。通过确保条件类型的形式,您可以使用分布式条件类型来执行此操作type FilterActionByType<A, T> = A extends ...
。将裸露A
作为选中的类型会触发所需的分布。
但是:您的条件类型的形式为type FilterActionByType<A, T> = A["type"] extends ...
,A
由属性查找“覆盖”,因此不是分布式的。这意味着,A["type"] extends ActionType
将采用的整个联合值A
,即(在您的情况下)ActionUnion
。并且ActionUnion["type"] extends "count/get"
变为("count/get" | "count/set") extends "count/get"
,这是错误的。(X extends (X | Y)
永远是正确的,但(X | Y) extends X
事实并非如此一般。)所以,你得到never
。
将您拥有的内容更改为分布式条件类型的最简单方法是将定义包装在A extends any ? ... : never
:
export type FilterActionByType<
A extends AnyAction,
ActionType extends string
> = A extends any ? A['type'] extends ActionType ? A : never : never;
type ActionUnion = Action<'count/get'> | Action<'count/set'>;
type CountGetAction = FilterActionByType<ActionUnion, 'count/get'>;
// type CountGetAction = Action<"count/get">
或者,您可以将原始条件类型重构为可分布的,而无需将其包装:
export type FilterActionByType<
A extends AnyAction,
ActionType extends string
> = A extends { type: ActionType } ? A : never;
type CountGetAction = FilterActionByType<ActionUnion, 'count/get'>;
// type CountGetAction = Action<"count/get">
该支票A extends {type: ActionType}
是的发行版本A["type"] extends ActionType
。
两种方法都可以为您工作,但是后者可能更干净。
好吧,希望能有所帮助;祝好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句