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
sayHellofunction, output "Hello {firstName}" if thecontactparameter is aPersonusing theassertIsPersontype 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
sayHellofunction implementation so that it outputs "Hello {name}" if thecontactparameter is anOrganisation. Remove the previous implementation for thePersontype.
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.