Passing types as arguments in Typescript
Asked Answered
U

2

8

i've written a custom hook to help me not repeat code for some fetch calls. it looks like this:

export const useCustomQuery = ({ endpoint, body, dataPoint }: args) => {
    const [data, setData] = useState()
    useEffect(() => {
        fetch(`http://localhost:4000/${endpoint}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body,
        })
            .then((res) => res.json())
            .then((res) => {
                if (dataPoint) {
                    setData(JSON.parse(res.data[dataPoint]))
                }
            })
    }, [endpoint, body, dataPoint])

    return { data }
}

but I'm getting some TS errors complaining about the type of data. is it possible to pass in the type as an argument as it might be different for each component that calls the hook? or what is the best way to approach this?

Uitlander answered 12/1, 2022 at 11:47 Comment(5)
Yes, you can use a generic type parameter and then either pass a type argument or allow TypeScript to infer it (if it can). (Commenting rather than answering as I assume there's a canonical question we can point this question at...)Pressing
boom. Generics. perfect, thanks broUitlander
Offtopic. This implementation has tons of issues because you do not cancel state updates that most likely wont be observable in dev env but would definitely hit you in production. Consider component got unmounted before the response came back. Or even worse if subsequent requests come out of order.Stradivarius
Check this question as an example #64393941 (BTW it uses generics).Stradivarius
@YuryTarabanko yeh I need to add error handling etcUitlander
C
10

You can use generic in this case. You can do something like this:

export const useCustomQuery = <T,>({ endpoint, body, dataPoint }: args) => {
    const [data, setData] = useState<T>()
    ...
}

This way, you are giving a type T when you call the hook useCustomQuery, that parameterized the type of data, like this:

useCustomQuery<MyType>({...})
Cripple answered 12/1, 2022 at 12:6 Comment(1)
Thank you! The missing comma after T stole my hours.Figuration
F
3

Yes, you can use generic types, here is an example. The type of generic functions is just like those of non-generic functions, with the type parameters listed first, similarly to function declarations, you need to specify the type whenever you call the hook in different components, the type will infer in that way.

function identity<Type>(arg: Type): Type {
  return arg;
}
 
let myIdentity: <Type>(arg: Type) => Type = identity;

You can refer to this link for more information.

Fazio answered 12/1, 2022 at 12:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.