Execute Program

Advanced TypeScript: Summary of Generic Type Parameters

Welcome to the Summary of Generic Type Parameters lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • We've seen generic type parameters in arrays, object types, and functions. This lesson will compare the type parameter syntax for each of those, as well as for interfaces.

  • Type parameter declarations always go inside <angle brackets>. The only question is where we put those angle brackets. For object types, classes, and interfaces, the answer is straightforward and consistent. The syntax is type MyType<T>, interface MyInterface<T>, and class MyClass<T>.

  • Here's a code problem:

    The Bag type, interface, and class below each try to use a type parameter, but none of them actually declare the parameter. Add the missing type parameter declarations.

    type Bag1<T> = {
    value: T
    };

    interface Bag2<T> {
    value: T
    }

    class Bag3<T> {
    value: T;
    constructor(value: T) {
    this.value = value;
    }
    }
    const bag1Number: Bag1<number> = {value: 1};
    const bag1String: Bag1<string> = {value: 'a'};
    const bag2Number: Bag2<number> = {value: 1};
    const bag2String: Bag2<string> = {value: 'a'};
    const bag3Number: Bag3<number> = {value: 1};
    const bag3String: Bag3<string> = {value: 'a'};
    [
    bag1Number.value,
    bag1String.value,
    bag2Number.value,
    bag2String.value,
    bag3Number.value,
    bag3String.value,
    ];
    Goal:
    [1, 'a', 1, 'a', 1, 'a']
    Yours:
    [1, 'a', 1, 'a', 1, 'a']Pass Icon
  • Function types are also consistent, but they feel a bit more "strange" than the examples above. When defining functions, type parameters go between function and the argument list:

  • >
    function returnsItsArgument<T>(arg: T): T {
    return arg;
    }

    [
    returnsItsArgument(1),
    returnsItsArgument('hello'),
    ];
    Result:
  • What if we want to define returnsItsArgument with an arrow function, rather than the function keyword? We could try to write the arrow function without any type parameter at all, like (arg) => arg. That's a type error due to the strictFunctionTypes compiler option that we saw in an earlier lesson.

  • >
    const returnsItsArgument = (arg) => arg;
    [
    returnsItsArgument(1),
    returnsItsArgument('hello'),
    ];
    Result:
    type error: Parameter 'arg' implicitly has an 'any' type.Pass Icon
  • To use a type parameter here, we have to put it before the function parameters: <T>(arg: T) => { ... }. That matches the function someFunction<T>(...) syntax: in both cases, the type parameters come immediately before the function parameters. Still, the arrow function syntax somehow feels a bit strange.

  • >
    const returnsItsArgument = <T>(arg: T): T => {
    return arg;
    };
    [
    returnsItsArgument(1),
    returnsItsArgument('hello'),
    ];
    Result:
    [1, 'hello']Pass Icon
  • Hybrid types (interfaces that are also functions) use the same syntax. The signature is written in exactly the same way as above, <T>(arg: T): T.

  • >
    interface ArgumentReturner {
    <T>(arg: T): T
    returnsArguments: true
    }

    const returnsItsArgument: ArgumentReturner = <T>(arg: T): T => {
    return arg;
    };
    returnsItsArgument.returnsArguments = true;
    [
    returnsItsArgument(2),
    returnsItsArgument('it worked'),
    ];
    Result:
    [2, 'it worked']Pass Icon
  • To summarize this lesson:

    • There are two general categories of type parameter syntax.
    • Types defined with the type, class, and interface keywords put their type parameters immediately after the type's name. For example, type Bag<T>.
    • Function types always put the type parameter immediately before the parameter list. For example, function f<T>(...), or const f = <T>(...).