I've just migrated my codebase from TypeScript 3.3 to 3.6 and found that the following code does not compile anymore:
declare const enum Api_Request_Type {
submit_chat_message = 1,
pull_chat_messages = 2,
battle_cheat = 50,
get_collection_page = 12,
}
type Api_Request = {
type: Api_Request_Type.submit_chat_message
request: {
message: string
}
response: {
messages: string[]
}
} | {
type: Api_Request_Type.pull_chat_messages
request: {}
response: {
messages: string[]
}
} | {
type: Api_Request_Type.battle_cheat
request: {
cheat: string
selected_unit_id: number
}
response: {
}
} | {
type: Api_Request_Type.get_collection_page
request: {
page: number
}
response: object[]
}
type Find_By_Type<Union, Type> = Union extends { type: Type } ? Union : never;
type Find_Request<T> = Find_By_Type<Api_Request, T>["request"]
type Find_Response<T> = Find_By_Type<Api_Request, T>["response"]
function api_request_callback<T extends Api_Request_Type>(type: T, data: Find_Request<T>, callback: (res: Find_Response<T>) => void): void {
fetch("api" + type, {
method: "POST",
body: JSON.stringify(data),
}).then(data => data.json()).then(data => {
callback(data as Find_Response<T>);
});
}
async function api_request<T extends Api_Request_Type>(type: T, data: Find_Request<T>): Promise<Find_Response<T>> {
return new Promise<Find_Response<T>>((resolve) => {
api_request_callback(type, data, (abc) => {});
});
}
And the error for it:
Argument of type '(abc: (Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T> | Find_By_Type<{ type: Api_Request_Type.pull_chat_messages; request: {}; response: { messages: string[]; }; }, T> | Find_By_Type<...> | Find_By_Type<...>)["response"]) => void' is not assignable to parameter of type '(res: (Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T> | Find_By_Type<{ type: Api_Request_Type.pull_chat_messages; request: {}; response: { messages: string[]; }; }, T> | Find_By_Type<...> | Find_By_Type<...>)["response"]) => void'.
Types of parameters 'abc' and 'res' are incompatible.
Type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>["response"] | Find_By_Type<{ type: Api_Request_Type.pull_chat_messages; request: {}; response: { messages: string[]; }; }, T>["response"] | Find_By_Type<...>["response"] | Find_By_Type<....' is not assignable to type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>["response"] & Find_By_Type<{ type: Api_Request_Type.pull_chat_messages; request: {}; response: { messages: string[]; }; }, T>["response"] & Find_By_Type<...>["response"] & Find_By_Type<....'.
Type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>["response"]' is not assignable to type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>["response"] & Find_By_Type<{ type: Api_Request_Type.pull_chat_messages; request: {}; response: { messages: string[]; }; }, T>["response"] & Find_By_Type<...>["response"] & Find_By_Type<....'.
Type '{ messages: string[]; }' is not assignable to type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>["response"] & Find_By_Type<{ type: Api_Request_Type.pull_chat_messages; request: {}; response: { messages: string[]; }; }, T>["response"] & Find_By_Type<...>["response"] & Find_By_Type<....'.
Type '{ messages: string[]; }' is not assignable to type 'Find_By_Type<{ type: Api_Request_Type.get_collection_page; request: { page: number; }; response: object[]; }, T>["response"]'.
Type '{ messages: string[]; }' is not assignable to type 'object[]'.
Type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>["response"]' is not assignable to type 'Find_By_Type<{ type: Api_Request_Type.get_collection_page; request: { page: number; }; response: object[]; }, T>["response"]'.
Type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>' is not assignable to type 'Find_By_Type<{ type: Api_Request_Type.get_collection_page; request: { page: number; }; response: object[]; }, T>'.
Type 'Find_By_Type<{ type: Api_Request_Type.submit_chat_message; request: { message: string; }; response: { messages: string[]; }; }, T>["response"]' is not assignable to type 'object[]'.
Type '{ messages: string[]; }' is missing the following properties from type 'object[]': length, pop, push, concat, and 25 more.
The error is rather cryptic due to it containing all the type information, but basically it's saying that there is a type mismatch between the abc in (abc) => {} and the res: FindResponse<T> in the api_request_callback signature. This code used to compile in 3.3 and makes sense to me why it would.
I'm sure the error is legit but I just don't understand why and how would I go about fixing it.