skip to Main Content

I have a function that calls api and returns a data of for example array of strings.

async function getData(){
   const response = await fetchData()
   return response
}

so the function signature is fixed to getData: () => string[]
now I need to be able to pass some processor function that would transform the response.
Like

async function getData<T>(process?: (data: Awaited<ReturnType<typeof fetchData>>) => T){
   const response = await fetchData()
   return process ? process(response) : response
}

but I get unknown type when this function is called

const result = await getData()
        ^
    unknown type

The desired result is to get as type string[] when process is not passed and return the T when process is there
also would be awesome to make T optional

2

Answers


  1. You can use conditional types:

    async function getData<T = string[]>(process?: (data: Awaited<ReturnType<typeof fetchData>>) => T): Promise<typeof process extends undefined ? string[] : T> {
        const response = await fetchData()
        return (process ? process(response) : response) as any
    }
    

    Here’s playground

    Login or Signup to reply.
  2. You can use a function overload signature to infer the correct return type for your case:

    TS Playground

    declare function fetchData(): Promise<string[]>;
    
    async function getData(): Promise<Awaited<ReturnType<typeof fetchData>>>;
    async function getData<T>(
      process: (data: Awaited<ReturnType<typeof fetchData>>) => T,
    ): Promise<T>;
    async function getData<T>(
      maybeProcess: ((data: Awaited<ReturnType<typeof fetchData>>) => T) | undefined,
    ): Promise<T | Awaited<ReturnType<typeof fetchData>>>;
    async function getData<T>(
      process?: (data: Awaited<ReturnType<typeof fetchData>>) => T,
    ) {
      const response = await fetchData();
      return process ? process(response) : response;
    }
    
    const r1 = await getData();
        //^? const r1: string[]
    
    const r2 = await getData((data) => data.length);
        //^? const r2: number
    
    declare const maybeProcess: ((data: string[]) => number) | undefined;
    const r3 = await getData(maybeProcess);
        //^? const r3: number | string[]
    
    

    Be sure to check the documentation for the compiler option exactOptionalPropertyTypes, which enables stricter handling of optional types.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search