All Things Typescript

Share this post
Mid-week Scoop: Comparing Functions in Typescript
www.allthingstypescript.dev
Mid-week Scoop

Mid-week Scoop: Comparing Functions in Typescript

Taking a look at how Typescript compares functions to check whether one function type is assignable to another function Type.

Maina Wycliffe
Sep 8, 2022
3
Share this post
Mid-week Scoop: Comparing Functions in Typescript
www.allthingstypescript.dev

In a previous issue, I looked into structural typing in Typescript but focussed on object literals mostly (you can find the previous article here). In this scoop, I want to look closely at something closely related to structural typing in Typescript and how comparing functions works in Typescript.

Thanks for reading All Things Typescript! Subscribe for free to receive new posts and support my work.

So, without further ado:

So, how does Typescript compare two functions and determine whether they are assignable to each other? Let’s take the following function Types:

type F1 = () => void;
type F2 = (input1: string) => void;

In Typescript, we can assign a variable typed as F2 above to FI, but not vice versa:


let f1: F1 = () => {
    console.log("F1")
}

// this is okay
let f2: F2 = f1;

// this will error
let f3: F1 = f2;
//   ^ Type 'F2' is not assignable to type 'F1'

Why? In this case, typescript mirrors this behavior from Javascript, where it’s quite common to ignore extra parameters of functions when we are not using them. Remember, Typescript compiles to Javascript and adds a typing system (mostly) on top of the features that Javascript provides; this means mirroring some of the behavior from Javascript whenever it doesn’t compromise Type Safety.

The reason for this assignment to be allowed is that ignoring extra function parameters is actually quite common in JavaScript. For example, Array#forEach provides three parameters to the callback function: the array element, its index, and the containing array. Nevertheless, it’s very useful to provide a callback that only uses the first parameter

Link to docs.

Typescript will not allow you to provide function parameter types that do not match the parameter types in each position. If we tried to do the opposite, assigning a function typed as F2 to another function typed as F1, then Typescript will complain.

let f1: F1 = () => {
    console.log("F1")
}

// this is okay
let f2: F2 = f1;

// this will error
let f3: F1 = f2;
//   ^ Type 'F2' is not assignable to type 'F1'

With the F2 type having a required input parameter - input1 - it makes sense since the F1 type doesn’t have any parameters.

Optional Parameters

If we made the input1 parameter optional for the F2 function, then typescript would stop complaining.

type F1 = () => void;
type F2 = (input1?: string) => void;

let f1: F1 = () => {
    console.log("F1")
}

// this is okay
let f2: F2 = f1;

// this is okay now
let f3: F1 = f2;

This behavior is also mirrored from Javascript behavior, and since optional parameters are undefined when they are not supplied/provided in Javascript, hence why Typescript allows this behavior. This behavior is unsound from a type-system perspective. Still, one that is allowed by the Typescript Type System, which has to take into account the runtime behavior of Javascript, and this is why the Typescript system is said to be unsound; I will explore this in a future issue.

Conclusion

In this week’s scoop, we covered structural typing in functions. Understanding this behavior is essential when writing and reading Typescript code, and it will help you form a much better mental model for what to expect from Typescript as you continue working with it.

Thanks for reading All Things Typescript! Subscribe for free to receive new posts and support my work.

Share this post
Mid-week Scoop: Comparing Functions in Typescript
www.allthingstypescript.dev
Previous
Next
Comments
TopNewCommunity

No posts

Ready for more?

© 2023 Maina Wycliffe
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing