gocardless-nodejs icon indicating copy to clipboard operation
gocardless-nodejs copied to clipboard

Typescript experience is not great

Open maximelebastard opened this issue 2 years ago • 4 comments

Hi

I guess you guys have put a lot of efforts in adding typescript support for a lib that wasn't originally designed for it - and thank you for that.

But it seems the typescript support is incomplete and not conveinient - which in the end gives more difficulties than help. I think it could be improved by changing a few things I listed there and that I (and probably others) have found confusing.

Expected

As the library provides Typescript definitions, I'd like to rely on them to speed up the developments and learn the API faster through autocompletion - so that I get more time for my core business.

Actual

Through a very simple use case (listing clients), I experienced 3 issues with the provided typings:

Issue 1: Importing the index is not enough

Expectation:

As 99% of the libs on npm, I expect to import the lib name and use it

import GC from "gocardless-nodejs"

const client = new GC(...);
// or
const client = new GC.Client(...);

// and for other exports from the lib
const res = await client.customers.list({ sort_field: GC.constants.CustomerSortField.CreatedAt });

Actual:

import GC from "gocardless-nodejs"
import { GoCardlessClient } from "gocardless-nodejs/client";
import { CustomerSortField } from "gocardless-nodejs/constants";

const client = new GC(...); // does not work
const client = new GC.GoCardlessClient(...); // does not work
const client = new GC.Client(...); // does not work

const client = new GoCardlessClient(); // works from a second import

// and a third import for the consts
const res = await gc.customers.list({ sort_field: CustomerSortField.CreatedAt });

Issue 2: The typescript structure do not match the NodeJS doc of the lib

Expectation:

The README.md of the lib gives the following Getting Started

// Initialise the client.
const client = gocardless(
  process.env.GC_ACCESS_TOKEN,
  constants.Environments.Sandbox,
  { raiseOnIdempotencyConflict: true },
);

Therefore, I expect to use the example - with the power of typescript

Actual:

This does not work

// Initialise the client.
const client = gocardless(
  process.env.GC_ACCESS_TOKEN,
  constants.Environments.Sandbox,
  { raiseOnIdempotencyConflict: true },
);

I had to dig into the lib and to find the issue #125 to find out that Typescript has a totally different contract

import { Environments } from "gocardless-nodejs/constants";
import { GoCardlessClient } from "gocardless-nodejs/client";
const client = new GoCardlessClient("your_access_token_here", Environments.Sandbox);

Issue 3: I get unexpected typing behaviors with documentation

Expectation:

I could pass an optional "after" parameter to gc.customers.list in order to paginate

const clients = await gc.customers.list({ limit: "10", sort_field: CustomerSortField.CreatedAt, sort_direction: CustomerSortDirection.Desc, ...(lastCursor != null ? { after: lastCursor } : {})  });

Actual:

This conditional spread causes a type error causing an implicit any of the return of the function.

maximelebastard avatar Jan 09 '23 17:01 maximelebastard