swellstores / swell-js

JS library for building storefronts and checkouts with Swell ecommerce.
https://swell.is
MIT License
136 stars 28 forks source link

TypeScript support #45

Open asia-jankowska00 opened 3 years ago

asia-jankowska00 commented 3 years ago

I'm writing my application in TypeScript and would like to see TypeScript typing support.

greph commented 3 years ago

Thanks @asia-jankowska00 for raising this issue. We're currently in the process of adding TS support. cc @rodrigo-swell

alinjie commented 2 years ago

Hi! Any progress on this issue?

greph commented 2 years ago

Hey @alinjie 👋 , no updates at the moment. Keep an eye on our change log for any announcements.

romainbriand commented 2 years ago

Hi! Anything new about this?

szydlovski commented 2 years ago

Seconded, it's a real turn off when you're used to a fully typed workflow.

markus-gx commented 1 year ago

news on this? :)

romainbriand commented 1 year ago

It would be so much appreciated + looks like a big part of the job has already been done in the past: https://github.com/swellstores/nextjs-commerce/tree/master/framework/swell/types

gusfune commented 1 year ago

I have the same request, but have decided to work on my own implementation of @types/swell-js as I develop with it on our internal codebases.

There is a lot to be typed still, but everything we're using seems to be correct. You can check progress or even copy it to an internal d.ts file from: https://github.com/gusfune/DefinitelyTyped - all commits in this fork are for typing Swell-JS

FelipeCabreraB commented 1 year ago

Hi @gusfune, thanks for all the work done! Although I'm having some trouble trying to implement your solution, I've copied the same files to my typescript Next.js project but it seems it's not working, I have the error that appears in the picture below, do you imagine any solution?

Screen Shot 2022-10-31 at 15 20 42
gusfune commented 1 year ago

The typing implementation is not fully done @FelipeCabreraB, so some types are written as any for now. Try to disable eslint warnings for those lines and see if it will work. Otherwise, might need to review your configuration.

gusfune commented 1 year ago

Oh, I forgot one thing, to use it inside a project you need to wrap the tipings with a declare module. Example:

declare module "swell-js" {
  export as namespace swell

  export interface Query {
    limit?: number
  ...ETC
}
FelipeCabreraB commented 1 year ago

Thanks @gusfune! That worked for me!

gusfune commented 1 year ago

One last update @FelipeCabreraB - you can now install @types/swell-js directly to your repository. It's been merged the PR I've made.

yarn add -D @types/swell-js or npm i -D @types/swell-js will do.

rodrigoddalmeida commented 1 year ago

Thanks @gusfune!

Additionally, we're including type definitions to swell-js itself, as well as including the remaining type definitions (avoiding any and unknown where possible).

For those who have custom models and fields, we'll be providing a facility to fetch matching response type definitions - that's further down the road, though.

artecoop commented 1 year ago

Why choosing to union in a single type both camel cased and snake cased interfaces? This introduces a load of errors as typescript can't infer which field is from, requiring to redeclare them.

gusfune commented 1 year ago

Why choosing to union in a single type both camel cased and snake cased interfaces? This introduces a load of errors as typescript can't infer which field is from, requiring to redeclare them.

Basically because when getting in the options useCamelCase could affect all returns and this was the easiest way to get the project started. Do you have any suggestions for us to improve? Let me know and we can adjust the project, or you can send a PR and become a maintainer as well.

artecoop commented 1 year ago

I for one use useCamelCase in my swell setup, but when I try to fetch a product, or a cart for example, I've been flooded with errors. I need to manually add all camel cased properties to snake case counterpart using declare module 'swell-js' {...}, which is inconvenient at the minimum

gusfune commented 1 year ago

I for one use useCamelCase in my swell setup, but when I try to fetch a product, or a cart for example, I've been flooded with errors. I need to manually add all camel cased properties to snake case counterpart using declare module 'swell-js' {...}, which is inconvenient at the minimum

Can you share a code snippet that's throwing errors so I can look at it? I have not faced the same problem, but we might find a solution.

artecoop commented 1 year ago

Sure, here's an example of error:

Screenshot 2022-12-30 at 12 47 40

I'm using SolidJS and cart?.state.current? is the result of

export interface CartContextState {
    current?: Cart | undefined;
    count: number;
}

const [state, setState] = createStore<CartContextState>({ count: 0 });

const cart: Cart = await Swell.cart.get();
if (cart) {
    setState({ current: cart, count: cart.itemQuantity });
}
gusfune commented 1 year ago

Sure, here's an example of error: Screenshot 2022-12-30 at 12 47 40

I'm using SolidJS and cart?.state.current? is the result of

export interface CartContextState {
    current?: Cart | undefined;
    count: number;
}

const [state, setState] = createStore<CartContextState>({ count: 0 });

const cart: Cart = await Swell.cart.get();
if (cart) {
    setState({ current: cart, count: cart.itemQuantity });
}

Ok, I had the same issue locally. The solution could be using the CamelCase types, this is how I am handling it until we find a better solution to identify the types.

So that would make the code:

export interface CartContextState {
    current?: CartCamelCase | undefined;
    count: number;
}

const [state, setState] = createStore<CartContextState>({ count: 0 });

const cart: CartCamelCase = await Swell.cart.get();
if (cart) {
    setState({ current: cart, count: cart.itemQuantity });
}

Not sure about SolidJS, but in React works like a charm.

@markus-gx do you have any ideas on this?

artecoop commented 1 year ago

I don't think is solidjs per se, more the combination of strictest tsconfig / eslint. Here's mine

tsconfig.json

{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "moduleResolution": "node",
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "jsx": "preserve",
        "jsxImportSource": "solid-js",
        "types": ["vite/client"],
        "noEmit": true,
        "isolatedModules": true,
        "strict": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "allowUnusedLabels": false,
        "allowUnreachableCode": false,
        "exactOptionalPropertyTypes": true,
        "noFallthroughCasesInSwitch": true,
        "noImplicitOverride": true,
        "noImplicitReturns": true,
        "noPropertyAccessFromIndexSignature": true,
        "noUncheckedIndexedAccess": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "importsNotUsedAsValues": "error",
        "checkJs": true,
        "baseUrl": "./",
        "paths": {
            "~/*": ["./src/*"]
        },
    }
}

and .eslintrc.cjs

module.exports = {
    env: {
        browser: true,
        es2021: true
    },
    parser: '@typescript-eslint/parser',
    plugins: ['solid'],
    extends: ['eslint:recommended', 'plugin:solid/typescript'],
    overrides: [],
    parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module'
    },
    rules: {}
};
gusfune commented 1 year ago

I don't think is solidjs per se, more the combination of strictest tsconfig / eslint. Here's mine

tsconfig.json

{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "moduleResolution": "node",
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "jsx": "preserve",
        "jsxImportSource": "solid-js",
        "types": ["vite/client"],
        "noEmit": true,
        "isolatedModules": true,
        "strict": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "allowUnusedLabels": false,
        "allowUnreachableCode": false,
        "exactOptionalPropertyTypes": true,
        "noFallthroughCasesInSwitch": true,
        "noImplicitOverride": true,
        "noImplicitReturns": true,
        "noPropertyAccessFromIndexSignature": true,
        "noUncheckedIndexedAccess": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "importsNotUsedAsValues": "error",
        "checkJs": true,
        "baseUrl": "./",
        "paths": {
            "~/*": ["./src/*"]
        },
    }
}

and .eslintrc.cjs

module.exports = {
    env: {
        browser: true,
        es2021: true
    },
    parser: '@typescript-eslint/parser',
    plugins: ['solid'],
    extends: ['eslint:recommended', 'plugin:solid/typescript'],
    overrides: [],
    parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module'
    },
    rules: {}
};

What I meant is, if you cast the results to CartCamelCase instead of Cart do you still get the errors mentioned? That'd be my suggestion for now. Here is an example of how I run this in react:

const res = await Swell.cart.update({
  billing:
    card: response.billing.
  },
}) as CartCamelCase

This would solve the issues. I also sent an example from your code that would probably fix the errors.

artecoop commented 1 year ago

I followed your hint and now works, but is ugly to override every single method. Hope to see a better implementation in the future.

gusfune commented 1 year ago

I followed your hint and now works, but is ugly to override every single method. Hope to see a better implementation in the future.

Glad that it worked! If you have any ideas on what we could do, let me know. Swell might take over the type maintenance sometime next year, so let's hope it's more seamless.

gusfune commented 1 year ago

I can update here that Swell has released typescript support and it's mostly functional as of 3.19.3. Some minor issues are listed on #81 but might be solved soon.