Home > Blockchain >  What is a generic type parameter T in TypeScript?
What is a generic type parameter T in TypeScript?

Time:12-23

Going through the TS handbook. https://www.typescriptlang.org/docs/handbook/2/functions.html

In TypeScript, generics are used when we want to describe a correspondence between two values. We do this by declaring a type parameter in the function signature:

function firstElement<Type>(arr: Type[]): Type | undefined {
  return arr[0];
}

By adding a type parameter Type to this function and using it in two places, we’ve created a link between the input of the function (the array) and the output (the return value). Now when we call it, a more specific type comes out:

In this case is Type a keyword? When I see just T is that the same thing?

Am I understanding this section correctly? By adding we are telling Typescript to assign whatever type the input is to the output?

CodePudding user response:

In this case is Type a keyword?

In your example, Type is a generic type parameter (type variable).

When I see just T is that the same thing?

Assuming the token is in the same position, yes.

By adding we are telling Typescript to assign whatever type the input is to the output?

It's helpful for me to think about them analogous to parameters in functions, but for types. You're effectively telling typescript this:

"I'm creating a type parameter (variable) called Type. I'm going to accept an argument in this function which will be an array, and you should use the type of each element in the array as the real type in place of Type. I'm going to return one of the array elements, so the return type of this function should be the same type as one of the array elements (or undefined if I use an index at which there's no value)."

Now, there's one more potentially confusing part to this, based on the example that you provided, which is "Why doesn't TypeScript account for the possibility of undefined when indexing an array element using square brackets?", and that's covered in this answer.

Here's a concrete example:

TS Playground

function firstElement<Type>(arr: Type[]): Type | undefined {
  return arr[0];
}

// This type is: number[]
const arr1 = [1, 2, 3];

// When giving `arr1` as the argument to `firstElement`,
// `Type` will become `number` because each element in `arr1`
// is `number`. So the result will be: number | undefined
const result1 = firstElement(arr1);

// This type is: string[]
const arr2 = ['hello', 'world'];

// When giving `arr2` as the argument to `firstElement`,
// `Type` will become `string` because each element in `arr2`
// is `string`. So the result will be: string | undefined
const result2 = firstElement(arr2);

Here's another example using T instead of Type for the generic type parameter:

TS Playground

function elementAtIndex<T>(arr: T[], index: number): T | undefined {
  return arr[index];
}

const arr = ['zero', 'one', 'two'];

const zero = elementAtIndex(arr, 0); // string | undefined
console.log(zero); // "zero"

const three = elementAtIndex(arr, 3); // string | undefined
console.log(three) // undefined

FWIW, elementAtIndex in the example above is just a functional version of Array.prototype.at(), which should be in an upcoming release of TypeScript (probably v4.6).

CodePudding user response:

No, here Type is a plain identifier, which identifies a type parameter. Normally type parameters are named with capital case letters, like T, but more descriptive names are useful.

This declaration says:

function firstElement   // We are defining a function
         <Type>         // The function has a type parameter
         (arr: Type[]): // and regular parameters of that type.
         Type | undefined // It returns either a value of the type
                          // given by the type parameter, or undefined.

The idea is that you may pass an array of elements of a particular type, and expect an element of that same type, statically checked:

firsElement<number>([1,2,3]) will return a number, and the compiler will guarantee that it won't be a string or an object.

firstElement<number>(['a', 'b']) won't even compile, because it is asking for an array of numbers (by <number>), but receives an array of strings.

firstElement<number>([]) will return undefined, because there is no first element to return. This is allowed by the | undefined clause in the return type.

  • Related