2

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;
};
5
  • 1
    Does this approach work for you or am I missing something? If it works I will write up an answer. Commented Jun 20, 2022 at 18:04
  • This is so great @jcalz and I think it has got me 99% of the way there, just like the other answer below! I've upvoted your answer thanks! But... When I have tried to create in practise I get an issue with the logic - please see this shorturl.at/dstET Commented Jun 21, 2022 at 0:37
  • Sorry, the above doesn't seem to work. tinyurl.com/2hd2x5bv Commented Jun 21, 2022 at 7:22
  • 1
    If the suggested solutions don't work for you, then you should edit your question to make your code a minimal reproducible example that demonstrates a situation where the proposed solutions fail. It should be plain text in the question itself (although having an additional link to an IDE is a good supplement, it's not a substitute for the plain text). Commented Jun 21, 2022 at 15:15
  • Oh, ok, thanks and apologies, @jcalz. I did originally try to write it in the comment, but I didn't have enough characters. I now realise the issue was more fundamental to my logic so I'll post a new question Commented Jun 22, 2022 at 22:31

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

3 Comments

Honestly, this is so good and I think it has got me 99% of the way there! I've upvoted your answer thanks! But... When I have tried to create in practise I get an issue with the logic - please see this shorturl.at/dstET
Sorry, the above doesn't seem to work. tinyurl.com/2hd2x5bv
@moroncodes it seems like typescript compiler is not super sophisticated when it comes to iterating over generic types (see this issue ). That being said I was able to fix your example by adding another generic to the data type. See: tinyurl.com/5wepe8e2 for more information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.