What is type widening and narrowing in Typescript?

In TypeScript, type widening and narrowing refer to the automatic adjustment of a variable's type based on its assigned value. Type widening occurs when TypeScript infers a broader type for a variable than its initially declared type, ensuring compatibility with a wider range of values. Type narrowing allows TypeScript to narrow down the type of a variable based on conditions or checks, enabling more precise type information and targeted operations. These mechanisms enhance the language's static type checking capabilities, promoting safer and more reliable code development.

Type widening

Type widening typically occurs when you declare a variable without explicitly specifying its type, and TypeScript determines the type based on the assigned value.

Code example

let num = 5; // Type of 'num' is inferred as number
let message = "Hello"; // Type of 'message' is inferred as string
console.log(num); // Output: 5
console.log(message); // Output: Hello

Code explanation

Lines 1–2: We assign values to num and message variables. TypeScript widens the types of the num and message variables based on their assigned values. The type inference mechanism infers that num should be of type number and message should be of type string.

Lines 4–5: We print the values of num and message variables.

Type narrowing

Type narrowing allows us to refine the type of a variable based on certain conditions. We can achieve this using various constructs such as type guards, type assertions, and control flow analysis.

Code example

Here's an example of type narrowing using a type guard:

function processValue(value: string | number) {
if (typeof value === "string") {
// Inside this block, 'value' is narrowed to type 'string'
console.log(value.toUpperCase());
} else {
// Inside this block, 'value' is narrowed to type 'number'
console.log(value.toFixed(2));
}
}
processValue("Hello"); // Output: HELLO
processValue(3.14159); // Output: 3.14

Code explanation

In the above example, the typeof type guard is used to narrow the type of the value parameter.

Lines 2–4: If the type of value is determined to be string, TypeScript narrows its type to string inside the corresponding code block.

Lines 5–7: If the type of value is determined to be number, TypeScript narrows it to number inside the else block.

Line 11: We call the processValue() function and pass a string value.

Line 12: The second call to processValue() function passes the argument 3.14159, which is a number. Since the type guard condition evaluates to false, the code block within the else statement executes. The number is then formatted with two decimal places using the toFixed() function, resulting in the output 3.14.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved