Learn TypeScript
Using a user-defined type guard with an assertion signature
Using a user-defined type guard with an assertion signature
In this lesson, we will learn what assertion signatures are and how we can use them in a user-defined type guard function.
Understanding an assertion signature
An assertion signature can be used in a function's return type to indicate the narrowed type of the parameter:
function assertTypeName( paramName: WideTypeName): asserts paramName is NarrowTypeName { if (some_check) { throw new Error("Assert failed"); }}
asserts paramName is NarrowTypeName
is the assertion signature in the above function.
The type guard function carries out some checks on its parameter and throws an error if it isn't the type being asserted. If no errors are raised, then TypeScript will narrow the type to the one being asserted.
An example
We are going to explore a user-defined type guard with an assertion signature in the TypeScript playground.
- Open the TypeScript playground by clicking the link below:
https://www.typescriptlang.org/play
Set the version to 3.7 or beyond.
Copy the code from below into the TypeScript playground:
interface Person { firstName: string; surname: string;}interface Organisation { name: string;}type Contact = Person | Organisation;function sayHello(contact: Contact) { // TODO - Output Hello {firstName} if a person // TODO - Output Hello {name} if an organisation}const bob: Person = { firstName: "Bob", surname: "Young",};const redBricks: Organisation = { name: "Red Bricks",};sayHello(bob);sayHello(redBricks);
This code is the same we have been using in the last few lessons.
- Let's create a user defined type guard to assert whether an object is a
Person
:
function assertIsPerson(contact: Contact): asserts contact is Person { if ((contact as Person).firstName === undefined) { throw new Error("Not a person"); }}
The assertion signature is asserts contact is Person
.
We are throwing an error if the firstName
property is undefined
. If the function returns without an error being raised, then the contact
parameter is asserted to be of type Person
.
- In the
sayHello
function, output "Hello {firstName}" if thecontact
parameter is aPerson
using theassertIsPerson
type guard:
function sayHello(contact: Contact) { assertIsPerson(contact); console.log("Hello " + contact.firstName);}
What is the type of contact
in the console.log
statement?
Neat!
- Create an assertion type guard, called
assertIsOrganisation
, to check whether an object is anOrganisation
.
- Change the
sayHello
function implementation so that it outputs "Hello {name}" if thecontact
parameter is anOrganisation
. Remove the previous implementation for thePerson
type.
What is the type of contact
in the console.log
statement?
Nice!
Summary
A user-defined type guard can carry out checks on its parameter and use an assertion signature to tell TypeScript what type it is. A user-defined type guard that uses an assertion signature throws an error if the checks fail.
In the next lesson, we will learn about the discriminated union pattern.