What <Angle Brackets> really mean in Typescript

I couldn’t find a gimp-friendly explanation of the use of angle brackets in Typescript, so I’m writing one myself. As a certified gimp, I endorse the comprehensibility of this explanation. My explanation is verbose, a brief explanation is provided in this stack overflow answer

What are angle brackets?

Angle brackets are the symbols < and >. As a novice at typescript and programming in general, I was confused by the various ways these were being used in code that I was mindlessly copying from stack overflow into my “own” project.

There are, as far as I can tell, three ways that the angle brackets are used in typescript:

  1. Type Parameters
  2. Type Arguments
  3. Type Assertions

1. Type Parameters

Problem: Say we have a function that takes some parameter and returns it, written as follows:

function returnTheSame(arg) {
return arg;
}

Currently the return type of the function is any . This is a problem because typescript won’t warn us if we happen to instruct returning an invalid property, like so:

returnTheSame('Hello').length  // <- This is valid as a string has a 
length property
returnTheSame({}).length // <- This is not valid, an empty object
does not have a length attribute, but
typescript will not warn us
returnTheSame({}).firstName // <- This property doesn't exist,
again no warning from Typescript

One way we could solve this is by specifying the type of the input parameters explicitly, in the fashion below. One may read this as “Only accept inputs of type string, and return an entity of type string” :

function returnTheSame(arg: string): string {
return arg;
}

However, we have sacrificed the generality of the function. It now only accepts strings. Perhaps we have a few different types that share common properties, and want to apply the function to all of them. What to do? What to do?

The function below can be read as “this function accepts the input of type T, and returns an output of the same type T”. Note that, crucially, it doesn’t insist upon you immediately defining type T :

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

T is a variable that will change depending on what you enter as an input. There is nothing special about the letter T, you could also write the following without any change in functionality:

function returnTheSame<typeVariable>(arg: typeVariable): typeVariable {
return arg;
}

Now, if we attempt the same instructions above, typescript will highlight errors:

returnTheSame({}).length // <- Error: TS2339: Property 'length' 
does not exist on type '{}'.
returnTheSame(null).firstName // <- Error: TS2339: Property
'firstName' does not exist on type
'{}'.

I can pass-in multiple generic types via these angled brackets, as I do in this example:

Below I have defined the function updateAddressRecord, which

  • takes an object of miscellaneous user data, which might include many unrelated user info properties, and an object of address information
  • returns an updated object of address information
function updateAddressRecord<T1 extends T2, T2>(contactInfo: T1, address: T2): T2 {
let key: keyof typeof address
for (key in address) {
if (address[key] !== contactInfo[key]) {
address = {...address, k: contactInfo[key]}
}
}
console.log(address);
return address
}

Note, here is an excellent explanation of keyof typeof.

I do not need to explicitly specify what the objects contactInfo and address are, I just need to ensure that the type of contactInfo includes all the fields in address (as its type, T1 , extends T2 ).

Run the function with these inputs to see:

updateAddressRecord({
firstName: "Boris",
surname: "Johnson",
occupation: "MP",
number: 99,
street: "Somewhere Street",
city: "London",
country: "United Kingdom"
},
{
number: 10,
street: "Downing Street",
city: "London",
country: "United Kingdom"
})

2. Type Arguments

Closely related to the setting of type parameters above, we may also use angle brackets to explicitly declare types when invoking a function. For instance, at some point I may want to use the function to explicitly accept strings, I can write:

returnTheSame<string>("Hello")

Here I have explicitly declared that the function will have an input argument of a string, and return a string, ensuring that typescript will throw an error if I do not satisfy this requirement.

3. Type Assertions

Typescript documentation says it best:

“Sometimes you will have information about the type of a value that TypeScript can’t know about.

For example, if you’re using document.getElementById, TypeScript only knows that this will return some kind of HTMLElement, but you might know that your page will always have an HTMLCanvasElement with a given ID.”

We may asset types either by writing as

const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

Or, interchangeably, using old mate angle brackets

const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store