Typescript: conditional generic Type

Viewed 58

Is it possible to write a function with types (similar to the one at bottom) so that it can be used in the following ways. Either;

parseApiResponse(apiResponse); // returns TParsedResponse
// or
parseApiResponse<TSpecificParsedResponse>(apiResponse); // returns TSpecificParsedResponse

where

type TApiResponse = {/* some complex non-specific raw data */}
type TParsedResponse = {[key:string]: string | number}[] // array of objects with any string as a key
type TSpecificParsedResponse = {name:string, age:number}[]

Here's my shoddy first attempt

const parseApiResponse = <T extends {}>(apiResponse: TApiResponse): T => {
  //some code here
  return parsedResponse;
};
1 Answers

This is a really good use case for extends in Typescript.

Here is the full code example

The main idea is that have a generic type that extends the base type.

function parseApiResponse<T extends TParsedResponse>(apiResponse: TApiResponse){
    // ... process
    const parsedResponce: T = [{}] as T
    return parsedResponce
}

Typescript will infer the "extended" type if it is not passed and will use the more specify one if it is passed.

Here is the full code example in case the Playground link above does not work.

type TParsedResponse = {[key:string]: string | number}[] // array of objects with any string as a key
type TSpecificParsedResponse = {name:string, age:number}[]

function parseApiResponse<T extends TParsedResponse>(apiResponse: TApiResponse){
    // ... process
    const parsedResponce: T = [{}] as T
    return parsedResponce
}

const exampleOne = parseApiResponse({complex: 'foo'}); // returns TParsedResponse
// or
const exampleTwo = parseApiResponse<TSpecificParsedResponse>({complex: 'foo'}); // returns TSpecificParsedResponse

Related