Check out a free preview of the full TypeScript 5+ Fundamentals, v4 course:
The "Generics Best Practices" Lesson is part of the full, TypeScript 5+ Fundamentals, v4 course featured in this preview video. Here's what you'd learn in this lesson:

Mike gives advice on best practices for using type parameters in TypeScript functions. An example of a function with two generic types and a demonstration of how inference works for both type parameters are also provided this segment.

Get Unlimited Access Now

Transcript from the "Generics Best Practices" Lesson

[00:00:00]
>> Here is my advice. Actually, I already did this step on the fly here where I fixed the listToDict function. Here's my advice when it comes to best practices here. You want to make sure that type params are used more than once in a function signature. Here's a case where it's not, where we're creating a function called returnAs and we take in an argument, that's an any, we return a T.

[00:00:35] And first off, It's gonna default to something that's not very useful. It'll force us to explicitly provide a type param here. Yeah, okay, this will be a number, we could do this too. It's just not a very safe, right? All we're doing here is casting. This is literally, the way we would describe this is convenient casting.

[00:01:07] And I don't consider this to be a valid use of generics. Generics, these type params, need to show up more than once in a function signature. Because essentially what we're doing is we're describing relationships between things. For example, here we're saying there is a relationship between the type of the argument you pass me and the type of what I returned.

[00:01:34] Now, it's not exactly the same type, but I'm using the type you gave me to create that return type. If you look at our listToDict function, look how many relationships there are. There's the array of things that we pass in. That has to align with the callback that we use to determine the ID of each item in the list of PhoneInfos.

[00:01:59] And that all is used to create the right return type, here. So these are places where there are clear relationships between the things. That's the point of the type param, effectively. It's to connect all of these things together and still give you that level of flexibility. Whereas, and you'll note, it's not a coincidence, inference is doing a lot for us here.

[00:02:26] It's doing nothing for us down here because there are no relationships to define here. The type parameter is just used as a return type. I'm not doing this, right? Like here, okay, it's trying. Now it's saying, all right, string. You thought this was a string, right? But it's not.

[00:02:46] Here it's trying to infer. It's just passing it straight through. This is like the identity function, f of x equals x. So just try to make sure that you are using type params more than once in a function signature. And if you wanna learn more, take intermediate TypeScript, because we will pick up right where we left off right here.

[00:03:11] So Luis asks is it, can we show an example of two generic types? Sure, here we go. So look at that, makeTuple. There's a number, number. There's a string and window intersected with type of global this. And you can see I have to type params. Inference is working on both T and U.

[00:04:10] We're using both type params twice, once in the arguments list, once in the return type. Here's how inference is working for us, check that out, number number. Here it's string. And then there's our window and type of globalThis. So there's an example using to two type params, two generics.

[00:04:28] I assume that's what you meant. Generics described as the kind of code you can write with type params. Cuz it's generic, right, we have a reusable listToDict function now that can be used without losing type information on a variety of different lists.