#### Type Inference in TypeScript: Understanding Contextual Typing

In this video, you will learn how Contextual Typing works in TypeScript.

#### Code

let amount = 99.9let isDebit = true;function multiply(a: number, b = 10) {return a * b;}type Transaction = { amount: number, isDebit: boolean };type TotalExpenses = (...transactions: Transaction[]) => number;const totalExpenses: TotalExpenses = (...ts) => {const debitTransactions = ts.filter(_ => _.isDebit);return debitTransactions.reduce((sum, t) => sum + t.amount, 0)}const t1: Transaction = { amount: 10, isDebit: true };const t2: Transaction = { amount: 20, isDebit: true };const total = totalExpenses(t1, t2);console.log(total)

The interactive code is available at TypeScript Playground

#### Full Transcript

Hello Friends, It's Harit from BonsaiiLabs. Today, I will explain how Contextual Typing works in TypeScript.

To start, I will create 2 variables called `amount`

, and `isDebit`

with values. Now, as I hover on the `amount`

, we can see that TypeScript inferred its type as a `number`

. For `isDebit`

, the type inferred is `boolean`

.

Now, I will create a new function called `multiply`

. It has 2 parameters - `a`

which I said is of type `number`

, and `b`

, for which I used parameter default, and did not specify the type of the variable. In the function body, I return the multiplication of `a`

and `b`

. Now, as I hover on `multiply`

, we can see that TypeScript inferred the type of `b`

as a `number`

. It did so by looking at the value on its right-hand side which is `10`

, and therefore concluded that `b`

must be of type `number`

. It also inferred the return type of function as the `number`

as multiplying two numbers yields a number.

So, in these examples, TypeScript inferred the type of the variable by looking at the values on the right-hand side of the expression.

Now, in the case of Contextual typing, the type inference works by looking at the left-hand side and filling the types on the right hand-side. Let me give you an example.

I will first create a type called `Transaction`

with 2 members called `amount`

of type `number`

, and `isDebit`

of type `boolean`

. Next, I will create another type called `TotalExpenses`

which represents a function signature. It takes a rest parameter called `transactions`

which is of type `Transaction[]`

and returns a `number`

. Now, since this is a type declaration only, we need to implement a function which is of type `TotalExpenses`

.

For that, I will create a constant called `totalExpenses()`

of type `TotalExpenses`

. Now, after the equals sign, as I open parentheses, we see that TypeScript presents a pop-up and guides us to fill the details according to what it expects. It expects one or more transactions and wants an implementation that returns a `number`

. Now, this is contextual typing, as the left side of the expression is guiding the types on the right-hand side. This is the opposite of how types were inferred in the previous examples.

I will add the parameter as `ts`

and open the curly braces for implementation. Right now, TypeScript shows an error. As I hover, it tells us that this method should return a `number`

, and currently, it is returning `void`

. In JavaScript, if you do not return a value from the function, it returns `void`

, which is the same behavior in TypeScript and that's how it compares the `void`

with the expected type `number`

and throwing an error. I will create a constant called `debitTransactions`

which will contain all the transactions where `isDebit`

is `true`

. Now see as I hit dot after `ts`

, I get all the methods that exist on an array. This is fantastic, I did not explicitly say that `ts`

is of type `Transaction[]`

, but because of contextual typing TypeScript knows that `ts`

is an array and provides us with all the methods that exist on an array. I will call filter and only take out the debit transactions. Next, I will run `reduce`

method on `debitTransactions`

and add the `amount`

field. I get an error since I did not provide the initial value of the accumulator, it picked the first transaction as the initial value which is a `Transaction`

, and therefore says that we cannot add a `Transaction`

and a `number`

. I will add `0`

as the initial value, and the code compiles successfully. So, you may now appreciate how contextual typing is a useful type inference technique and guides developers in writing correct implementation without adding the types over and over again.

Let's test our implementation next! I will add 2 debit transactions with different amounts. I will then call `totalExpenses()`

with `t1`

and `t2`

and save the result in a variable called `total`

. I will finally print the value on the console and execute this code. We can confirm that this code works correctly.

Great, so I hope you now understand what Contextual Typing is and how it works in TypeScript. Thank you for your time, and I will see you again in another video.