The intricate nature of a generic asynchronous return type hinders the ability to accurately deduce precise

My goal in this coding playground is to create a versatile API handler helper that guarantees standard response types and also utilizes inference to ensure our application code can effectively handle all potential scenarios:

Visit the Playground

However, I'm encountering issues with the inference failing to correctly deduce these generics. Does anyone have any suggestions on how to reorganize this to improve the inference process? Thank you!

import { Jsonifiable, AsyncReturnType } from "type-library";
import z, { ZodTypeAny } from "zod";

...

// These outcomes turn out to be too general
// Expecting {foo: "bar"} but receiving Jsonifiable
type successResponse = Extract<AsyncReturnType<typeof apiHandler>, {success: true}>
type errorResponse = Extract<AsyncReturnType<typeof apiHandler>, {success: false}>
type code = errorResponse["code"]; // Hoping for "too big" | "too small", but getting a string

Answer №1

Utilize type parameters to represent individual type arguments for success/error response types instead of using a type parameter to represent them as a whole. This approach simplifies type inference for the compiler.

function createApiHandler<
  TInputSchema extends ZodTypeAny,
  const TSuccessData extends Jsonifiable,
  const TErrorCode extends string,
  const TErrorData extends Jsonifiable,
>(
  inputSchema: JsonifiableSchema<TInputSchema>,
  handler: (input: z.infer<TInputSchema>) => Promise<SuccessResponse<TSuccessData> | ErrorResponse<TErrorCode, TErrorData>>
): typeof handler {
  return (input: unknown) => handler(inputSchema.parse(input));
}

Playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to ensure that the base class Resolver finishes before allowing the derived class Resolver to execute?

I have a situation where many of my resolvers (@angular/router Resolve) need to query the same data before executing their route-specific queries. To streamline this process, I want to create a resolver base class that resolves the initial data before the ...

What is the procedure for including a js file in typescript?

I am trying to import a js file in typescript and access objects and functions within the file. I have added the js file in index.html, but it is not working as expected. I tried using "import '[js file path]'" but it did not work. import { Comp ...

Leveraging ES Module packages in Azure TypeScript Function Development

I'm encountering an issue while trying to utilize the p-map package in my Azure Function. The error message that I'm getting is as follows: A Worker failed to load function: 'serverless' with function id: '<id>'. Result: ...

How can one properly extend the Object class in JavaScript?

I have a scenario where I want to enhance a record (plain Javascript object) of arrays with additional properties/methods, ideally by instantiating a new class: class Dataframe extends Object { _nrow: number; _ncol: number; _identity: number[]; co ...

Ways to verify whether a checkbox is selected and store the status in the LocalStorage

Hey there, I'm still new to the world of programming and currently just a junior developer. I have a list of checkboxes and I want to save any unchecked checkbox to my local storage when it's unselected. Below is a snippet of my code but I feel l ...

What is the correct way to convert a base type value to its extended type in TypeScript?

Consider the TypeScript code block below: type URLEx = URL & { custom: string; }; const url = new URL("http://localhost:3000/foo/var"); const url_x: URLEx = { ...url, custom: "hello", }; console.log(url); // Output properti ...

*ngFor is not rendering

I understand that this question is frequently asked, but the usual solutions don't seem to be effective in this case. Here is my code snippet: export class CourseReviewFormComponent implements OnInit { form: FormGroup questionnaire: string[] = [] ...

getItemForm does not make a second promise call

I have a scenario where my function calls the api.send service twice, however when I run a test expecting it to resolve both promises, only res1 is returned and not res2. How can I ensure that both promises are resolved successfully? Here is my function: ...

Modify the Text Displayed in Static Date and Time Picker Material-UI

Looking to update the title text on the StaticDateTimePicker component? Check out this image for guidance. In the DOM, you'll find it as shown in this image. Referring to the API documentation, I learned that I need to work with components: Toolbar ...

Using an object hierarchy in Typescript to create an if statement

Currently, I am attempting to create a logical statement using a hierarchy structure as shown below: if ((config.elementConfig.curve[0].dataset[0].splitBy = 'my discrete var')) {..... However, when implementing this statement, I encounter the er ...

Tips for sending user IDs through an Angular 8 interceptor

Alright, In my Angular application that is using version 8, I have an HttpMaintenanceInterceptor configured without the use of cookies. Instead, I have a getAccessToken method within the authService as shown below: getAccessToken(): string { return ...

The Google Maps API is throwing an error because it cannot access the property 'nativeElement' of an undefined object

I'm currently using Google Maps and I want to display the map only if a certain condition is true. HTML: <div *ngIf="anyboolToShowMapOrNot" #map id="map"></div> Here's my TypeScript code: @ViewChild("map",{static: true}) mapEle ...

Can you identify the specific error type that occurs in the onError function of react-query's MutationCache when using Typescript

Can someone help me with identifying the type of error in react-query MutationCache onError function when using Typescript? I also need guidance on how to override the type so that I can access and use the fullMessage from the data. const queryClient = new ...

What is the counterpart of $.isEmptyObject({}) in Typescript for checking if an object is

Is there a formal method for testing an Object (response from server) to see if it is empty? Currently, I am using jQuery to accomplish this. this.http.post(url, data, {headers: headers}).then( result => { if (!$.isEmptyObject(result ...

Completely turn off type checking for all files within the *.test.* extension, including imported components

"exclude": ["*.test.ts", "*.test.tsx"] in the tsconfig file only stops type checking for test-specific types like describe, it, expect, etc. However, errors still appear for imported Components in every test file in vscode. The only way to remove these err ...

Error in TypeScript: The property 'data' is not found within type '{ children?: ReactNode; }'. (ts2339)

Question I am currently working on a project using BlitzJS. While fetching some data, I encountered a Typescript issue that says: Property 'data' does not exist on type '{ children?: ReactNode; }'.ts(2339) import { BlitzPage } from &q ...

What is the proper way to specify the type for a proxy that encapsulates a third-party class?

I have developed a unique approach to enhancing Firestore's Query class by implementing a Proxy wrapper. The role of my proxy is twofold: If a function is called on the proxy, which exists in the Query class, the proxy will direct that function call ...

Is it feasible to programmatically define the onClick action for an element within a ReactNode?

Let's discuss a function called addAlert that adds messages to an array for display as React Bootstrap alerts. While most alerts are simple text, there's one that comes with an "undo the last action" link. The challenge is that when this "undo" l ...

What changes can be implemented to convert this function to an asynchronous one?

Is it possible to convert the following function into an asynchronous function? getHandledSheet(): void { this.timesheetService.getAllTimesheets().subscribe({next: (response: TimeSheet[]) => {this.timesheetsHandled = response.filter(sheet => ...

Issue detected in rxjs-compat operator's shareReplay file at line 2, column 10:

I've encountered an issue with the angular material spinner I'm using in my project. The error message is as follows: ERROR in node_modules/rxjs-compat/operator/shareReplay.d.ts(2,10): error TS2305: Module '"D:/ControlCenter/ofservices ...