In TypeScript, a Union Type is made by combining more than one type. So to access or get the properties and method of a single type when using union type on a variable, we have to narrow the variable type we need using an if conditional statement check
and by using the typeof
operator to check the type of the variable value in TypeScript.
This process is also called Narrowing types
in TypeScript.
TL;DR
// union type declaration
let nums: string | number;
// Dynamically assign value to the variable nums
// In real life this would be a value from an API response
// Here we are just emulating the setting of the value
nums = true ? "Hello" : 1000;
if (typeof nums === "string") {
// now we can access string type
// methods and propreties here
const upperCase = nums.toUpperCase(); // toUpperCase() method is a string type method
console.log(upperCase); // HELLO
} else {
// we can access the number type
// methods and properties here
const precision = nums.toPrecision(2); // toPrecision() method is a number type method
console.log(precision); // 1.0e+3
}
For example, let's consider a variable called nums
which has a union type made of both the string
type and the number
type like this,
// union type declaration
let nums: string | number;
Now let's try to use the methods and properties available to us in the nums
variable. If you are using VSCode
as your code editor then it may show a autocomplete dropdown showing the methods and properties available to us like this,
As you can see from the above image that there are only 3 methods that the VSCode
editor's autocomplete dropdown is showing. This is because the nums
variable has a union type which is composed of both the string
and the number
type and thus it can only show the methods and properties common (or union) to both the string
and the number
type.
But what if we need the methods and properties of string
type. To do that we have to narrow down the type of the variable nums
using a conditional statement check
.
To do that let's use an if conditional statement check
and use the typeof
operator to check if the variable value is of type string
like this,
// union type declaration
let nums: string | number;
nums = "Hello";
if (typeof nums === "string") {
// now we can access string type
// methods and propreties here
const upperCase = nums.toUpperCase(); // toUpperCase() method is a string type method
console.log(upperCase); // HELLO
}
As you can see from the above code that the TypeScript compiler allowed us to use the toUpperCase()
string
type method inside the if
block since we have checked to see if the variable value is of type string
before getting into the if
block.
Now if we add an else
block to the above if
condition, the TypeScript compiler is intelligent to know that the other type we can use is the number
type. So let's try to access one of the methods of the number
type in the else
block like this,
// union type declaration
let nums: string | number;
// Dynamically assign value to the variable nums
// In real life this would be a value from an API response
// Here we are just emulating the setting of the value
nums = true ? "Hello" : 1000;
if (typeof nums === "string") {
// now we can access string type
// methods and propreties here
const upperCase = nums.toUpperCase(); // toUpperCase() method is a string type method
console.log(upperCase); // HELLO
} else {
// we can access the number type
// methods and properties here
const precision = nums.toPrecision(2); // toPrecision() method is a number type method
console.log(precision); // 1.0e+3
}
As you can see from the above code that the TypeScript compiler allowed us to use the toPrecision()
number
type method on the else block which is what we want to happen.
This means we have successfully type-checked against every possible scenario which may occur during the runtime of the program 🎉.
See the above code live in codesandbox.
That's all 😃!