打字稿通过联合类型中的参数 b 获取参数 a

时间:2021-05-20 14:11:57

标签: typescript

我有两个请求类型 AddInterestAreaRequestRemoveInterestAreaRequest。我想创建一个可以传入 action 的实用程序类型,它会返回 params

这是我所拥有的

type AddInterestAreaRequest = {
  action: 'addInterestArea';
  params: AddInterestAreaParams;
};

type RemoveInterestAreaRequest = {
  action: 'removeInterestArea';
  params: RemoveInterestAreaParams;
};

export type JSBRequest = {
  configs?: BridgeRequestConfigs;
} & (AddInterestAreaRequest | RemoveInterestAreaRequest);

type GetParamByAction<T extends JSBRequest['action']> =
  JSBRequest['action'] extends T ? never : JSBRequest['params'];

type Testing = GetParamByAction<'addInterestArea'>;


我所拥有的不起作用,TestingAddInterestAreaParams | RemoveInterestAreaParams 因为 JSBRequest['params'] 始终是 AddInterestAreaParams | RemoveInterestAreaParams

而且我基本上想让Testing成为唯一的AddInterestAreaParams

知道如何实现它吗?

谢谢。

3 个答案:

答案 0 :(得分:2)

您可以使用 discriminated union 在类型级别区分 the Extract<T, U> utility type,它过滤联合类型 T 并只保留那些可分配给 U 的成员:

type GetParamByAction<T extends JSBRequest['action']> =
    Extract<JSBRequest, { action: T }>["params"]    

因此 Extract<JSBRequest, {action: T}> 将仅返回 JSBRequestaction 属性可分配给 T 的那些成员,这应该正是您想要的。然后我们index进入它以获取它的 params 属性。

让我们确保它有效:

type Testing = GetParamByAction<'addInterestArea'>;
// type Testing = AddInterestAreaParams

看起来不错。

Playground link to code

答案 1 :(得分:0)

type GetParamByAction<T extends JSBRequest['action']> =
  T extends 'addInterestArea' ? AddInterestAreaRequest['params'] : RemoveInterestAreaRequest['params'];

type Testing = GetParamByAction<'addInterestArea'>;  // Should be AddInterestAreaParams

答案 2 :(得分:0)

在这种情况下,我建议先使用 TS 帮助程序 Extract 从联合中提取类型:

type GetJSBRequestByAction<T extends JSBRequest['action']> = Extract<JSBRequest, { action: T }>;


type Test1 = GetJSBRequestByAction<'addInterestArea'>;

// This gives:
// {
//    configs?: BridgeRequestConfigs;
// } & AddInterestAreaRequest

然后你就可以访问参数了:

type GetParamByAction<T extends JSBRequest['action']> = GetJSBRequestByAction<T>['params'];