notrab / react-use-cart

React hook library for managing cart state

Home Page:http://npm.im/react-use-cart

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Typescript intellisense

AaronLayton opened this issue · comments

Hiya folks!

Tried to use this in a project and if I try and add a product using addItem and then try to map over the items afterwards, Typescript doesn't seem to understand any of the other props that I passed in with my object. It is only doing intellisense on the Item

interface Item {
  id: string;
  price: number;
  quantity?: number;
  itemTotal?: number;
  [key: string]: any;
}

Seems to fully ignore [key: string]: any;

Is this expected behaviour?

We may need to allow you to pass a generic type that is merged with the item type. Happy to accept any PRs to fix this 😅

I have been experimenting with building a library similar to this for internal use, but perhaps there is a better way.

I had to create a createCartContext factory function so I could pass in a type

// npm package
type Item<T extends {}> = T & {
    id: string;
    price: number;
    quantity?: number;
    itemTotal?: number;
}

interface CartProviderState<T> extends InitialState<T> {
    /* ... */
}

export function createCartContext<T>() {
    const context = createContext<CartProviderState<T>>(null);

    const Provider = ({ children, ...options }: CartProvider<T>) => {
        const cartState = getCartState<T>(options);

        return (
            <context.Provider value={cartState }>{children}</context.Provider>
        )
    }

    return {
        context .
        CartProvider,
        useCart: () => useContext(context)
    }    
}

Then after importing into my codebase I had to create the new Context

// /context/CartContext.ts
import { createCartContext } from './super-duper-cart`

const cartContext = createCartContext<BasketProduct>();

export const CartProvider = cartContext.CartProvider;
export const useCart = cartContext.useCart;

Nice!

I realise after this that with TypeScript you can have generic components, so could be worth making a Provider that accepts a generic

type MyBasketProduct {
    legLength: number
}

<CartProvider<MyBasketProduct> id="basket" onItemAdd={(item) => console.log(item)}>
    <MainApp />
</CartProvider>

To add onto this, I would like this to be updated as well:

interface CartProviderState extends InitialState {
    addItem: (item: Item, quantity?: number) => void;
    removeItem: (id: Item["id"]) => void;
    updateItem: (id: Item["id"], payload: object) => void;
    updateItemQuantity: (id: Item["id"], quantity: number) => void;
    emptyCart: () => void;
    getItem: (id: Item["id"]) => any | undefined;
    inCart: (id: Item["id"]) => boolean;
}

There is no setItems: (items: Item[]) => void; in here. I've added PR for this fix, let me know if its good to go because its my first ever code fix on open source.

Thanks for the PR @Skidragon 🚀

@AaronLayton this sounds really awesome - if you're up for it, feel free to PR, and I'll get it merged in 😄

Hi @AaronLayton are you working on this issue? It would be great if this is implemented.