【发布时间】:2022-01-16 05:57:21
【问题描述】:
我的目标是按操作对请求和响应进行分组,所以如果我有(如下面的代码)两个操作:Play 和 Stay,我将有一对代表请求的请求/响应/response of Play action 和 Stay action 相同。
我想表达一个约束只能耦合同一个动作的请求和响应(see Playground)
type ActionName = "Play" | "Stay";
type RequestD<A extends ActionName, B extends Record<string, unknown>> = {
_tag: "Request";
_action: A;
} & B;
type ResponseD<A extends ActionName, B extends Record<string, unknown>> = {
_tag: "Response";
_action: A;
} & B;
type PlayRequest = RequestD<"Play", { a: number }>;
type PlayResponse = ResponseD<"Play", { b: number }>;
type StayRequest = RequestD<"Stay", { c: number }>;
type StayResponse = ResponseD<"Stay", { d: number }>;
type ActionOf<X> = X extends RequestD<infer A, any>
? A
: X extends ResponseD<infer A, any>
? A
: never;
// Problem:
// X is "Play" | "Stay"`
// Is there a way to get "Play"?
type X = ActionOf<PlayRequest>;
type TagOf<X> = X extends RequestD<any, any>
? "Request"
: X extends ResponseD<any, any>
? "Response"
: never;
// Problem:
// Y1 is "Request" and that's expected
// Y2 is "Request" as well and that's unexpected, how is this possible? How can I fix it?
type Y1 = TagOf<PlayRequest>;
type Y2 = TagOf<PlayResponse>;
type RoundTrip<
A extends ActionName,
Req extends RequestD<A, any>,
Res extends ResponseD<A, any>
> = {
_action: A;
request: Req;
response: Res;
};
type PlayRT = RoundTrip<"Play", PlayRequest, PlayResponse>;
// Problem:
// The following should be wrong because the first request is related to action "Stay", not "Play"
// Is there a way to enforce that?
type WrongRT = RoundTrip<"Play", StayRequest, PlayResponse>;
我在上面的代码中提出的问题是:
- 如何将“播放”操作关联到请求/响应以在类型级别使用它?
- 为什么即使这些类型被适当标记(
_tag字段),我也无法区分请求/响应? - 如何将操作限制为
RoundTrip类型的请求/响应中的相同操作?
【问题讨论】:
标签: typescript typescript-generics