question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal for a new, more efficient typescript fetch code generation

See original GitHub issue

I’ve noticed that for larger API surface areas the code generated can grow exponentially. One way around this would be to use TypeScript more effectively to enforce standard fetch conventions.

This can be accomplished by generating primarily types, which have 0 bytes of output along with some helper code; this means that essentially no matter how large your API is, the generated code is always a consistent size of a few kilobytes.

/** Routes */
type AddUserRoute    = "/api/users";
type DeleteUserRoute = "/api/users";
type AddPostRoute    = "/api/posts";

/** Models */

type AddPostModel = {
    subject?: string
    body: string
}

type AddPostReturnModel = {
    id: number
}

type AddUserModel = {
    name: string
    age: number
}

type AddUserReturnModel = {
    id: number
}

type DeleteUserModel = { 
    id: number
};

type TypedRequestInit<T = any> = T | ({ model: any } & RequestInit);

type TypedResponse<T = any> = T;

/** Constants */
const defaultRequestInfo : RequestInit = {
    headers: {
        "Content-Type": "application/json"
    }
}

/** Overloads */

/** Generated Add Post description goes here */
async function fetchPost(info: AddPostRoute, init: TypedRequestInit<AddPostModel>): Promise<AddPostReturnModel>;

/** Generated Add User description goes here */
async function fetchPost(info: AddUserRoute, init: TypedRequestInit<AddUserModel>): Promise<AddUserReturnModel>;

async function fetchPost(info: RequestInfo, init: TypedRequestInit) {
    const response = await fetch(
        info,
        "model" in init 
            ? { method: "POST", ...defaultRequestInfo, ...init, body: JSON.stringify(init.model) }
            : { method: "POST", ...defaultRequestInfo, body: JSON.stringify(init) }
    );

    return await response.json();
}

/** Overloads */
async function fetchDelete(info: DeleteUserRoute, init: TypedRequestInit<DeleteUserModel>): Promise<Response>;

async function fetchDelete(info: string, init: TypedRequestInit) {
    let modelInInit = "model" in init;
    let model       = modelInInit ? init.model : init;
    let keys        = Object.keys(init)
    let qs          = "?";

    for (let i = 0; i < keys.length; ++i) {
        let key   = keys[i];
        let value = model[key];
        
        if (i > 0)
            qs += "&";

        qs += encodeURIComponent(key) + "=" + encodeURIComponent(value);
    }

    return await fetch(
        info + qs,
        modelInInit
            ? { method: "DELETE", ...defaultRequestInfo, ...init }
            : { method: "DELETE", ...defaultRequestInfo }
    );
}

/** Example Usage */
fetchPost("/api/users", { name: "Ted", age: 25 });
fetchPost("/api/posts", { body: "This is a test" });
fetchDelete("/api/users", { id: 5 });

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:4
  • Comments:14 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
onionhammercommented, Aug 1, 2020

Hey @RicoSuter and all - I just published my templates and some tests to the following repo:

https://github.com/wivuu/nswag-liquid-slim

The templates can be found here: https://github.com/wivuu/nswag-liquid-slim/tree/master/Templates

I’ve been using the templates in my app and so far they’re easy to use and pretty reliable! I’m making the license MIT so please feel free to incorporate them however you want; or if you don’t want to please let me know and I will probably create my own supplemental nuget package.

If anyone has any suggestions/improvements to reduce output or improve performance please feel free to submit PRs.

2reactions
onionhammercommented, May 29, 2020

Update:

I just converted my own application for a real-world usecase, here’s a before and after comparison

image

Most of the changes were very straighforward, for example:

image

Read more comments on GitHub >

github_iconTop Results From Across the Web

Improve TS file size
[Review] Reduce file size of the Angular typescript client #1469 opened by ... Proposal for a new, more efficient typescript fetch code generation...
Read more >
[Proposal] Untagged Variants for ReScript
The proposal includes a detailed design of the new type constructors, type inference, pattern matching, and handling of unknown values. We will ...
Read more >
A Proposal For Type Syntax in JavaScript - TypeScript
The idea of this proposal is that JavaScript could carve out a set of syntax for types that engines would entirely ignore, but...
Read more >
Introducing Codegen for Hydrogen: Automated Types ...
In this article, we'll explore how to manually incorporate types with the Storefront API, look at a pre-generated approach and then dive ...
Read more >
Node.js and TypeScript Tutorial: Build a CRUD API
Learn how to use TypeScript to build a feature-complete Express API. Learn how to use TypeScript with Express to create, read, update, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found