I am wondering if there's a way could let ts compiler determine the type of callback in useListenAPI
as
(data: number[]) => void
if eventType === APIType.API1(data: {isAdmin: boolean, data: number[]}) => void
if eventType === APIType.API2const enum APIType {
API1 = 1,
API2 = 2
}
interface API1{
type: APIType.API1,
Data: number[]
}
interface API2{
type: APIType.API2,
Data: {
isAdmin: boolean,
data: number[]
}
}
type UnionAPI = API1 | API2;
//ts error
//'eventType' refers to a value, but is being used as a type here. Did you mean 'typeof eventType'?
const useListenAPI = (eventType: APIType, callback: (data:Extract<UnionAPI,{type: eventType}>["Data"]) => void)) => {
// do whatever
}
//'type: typeof eventType' will make callback is (data: number[]|{isAdmin: boolean, data: number[]}) => void
const useListenAPI = (eventType: APIType, callback: (data:Extract<UnionAPI,{type: typeof eventType}>["Data"]) => void)) => {
// do whatever
}
I know it is solvable using generic like following but I am just wondering if there's a simpler version, or it is out of reach from ts compiler since it a runtime thing
const useListenAPI = <T,>(eventType: APIType, callback: (data:Extract<UnionAPI,{type: T}>["Data"]) => void)) => {
// do whatever
}
useListenAPI<APIType.API1>(APIType.API1, (data) => {
// data: number[]
})
You can use the function overloads.
Here is the example
// Overloads
function useListenAPI(eventType: APIType.API1, callback: (data: API1['Data']) => void): void;
function useListenAPI(eventType: APIType.API2, callback: (data: API2['Data']) => void): void;
function useListenAPI(eventType: APIType, callback: Function) {
// implementation details
}
// Usage
useListenAPI(APIType.API1, (data) => {
// data is number[]
});
useListenAPI(APIType.API2, (data) => {
// data is { isAdmin: boolean, data: number[] }
});
Here is the doc
https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads