This content originally appeared on Bits and Pieces - Medium and was authored by Brian Ridolce
TypeScript is a powerful, statically typed programming language that helps developers write more maintainable and scalable JavaScript code. One of its most powerful features is the ability to narrow types based on conditions, which can help developers write more robust and error-free code. In this article, we will explore multiple use cases where narrowing is important in TypeScript.
Use Case 1: Narrowing with APIs
When working with APIs, data can be returned in various formats, and TypeScript may not know the exact type of the data. Narrowing can be used to refine the type of the data based on the actual data received from the API.
For example, let’s assume we have an API that returns data about products. Initially, TypeScript may not know the exact type of the returned data. By using narrowing, we can refine the type of data based on the actual data returned from the API.
interface Product {
id: number;
name: string;
description: string;
price: number;
}
async function fetchProducts(): Promise<Product[] | null> {
// Fetch products from API
}
const products = await fetchProducts(); // fetch products from API
if (Array.isArray(products)) {
const product: Product = products[0]; // refine the type of products
console.log(product.name); // TypeScript knows that product has a name property
}
In the example above, we define an interface for a product and a function that fetches products from an API. Initially, the fetchProducts function may return null or an array of products, and TypeScript may not know the exact type of the returned data. By using narrowing, we refine the type of the returned data to an array of products, which allows us to access the properties of a product without any errors.
Use Case 2: Narrowing with React Components
In React, components can receive props of different types, and TypeScript may not know the exact type of the props. Narrowing can be used to refine the type of props based on their actual type.
For example, let’s assume we have a React component that receives a prop of type string or null. Initially, TypeScript may not know the exact type of the prop. By using narrowing, we can refine the type of the prop based on its actual type.
interface Props {
name: string | null;
}
const MyComponent: React.FC<Props> = ({ name }) => {
if (name !== null) {
console.log(name.toUpperCase()); // refine the type of name
}
return <div>{name}</div>;
};
In the example above, we define an interface for the props of a component, and a component that receives a name prop of type string or null. Initially, TypeScript may not know the exact type of the name prop. By using narrowing, we refine the type of the name prop to a string, which allows us to access the toUpperCase method without any errors.
Use Case 3: Narrowing with Conditional Statements
In TypeScript, conditional statements can be used to narrow types based on conditions. This can help developers write more robust and error-free code.
For example, let’s assume we have a function that receives a string or null, and we want to check if the string is not null before accessing its length property.
function printStringLength(str: string | null) {
if (str !== null) {
console.log(str.length); // refine the type of str
}
}
In the example above, we define a function that receives a string or null, and we use a conditional statement to check if the string is not null before accessing its length property. By using narrowing, we refine the type of the string to a non-null string, which allows us to access its length property without any errors.
Use Case 4: Narrowing with Union Types
In TypeScript, union types can be used to define a type that can be one of several possible types. Narrowing can be used to refine the type of a variable based on the actual type of the value.
For example, let’s assume we have a function that receives an argument of type number or string, and we want to check if the argument is a number before performing some calculations.
function calculateSum(arg: number | string) {
if (typeof arg === 'number') {
console.log(arg + 10); // refine the type of arg
}
}
In the example above, we define a function that receives an argument of type number or string, and we use typeof to check if the argument is a number before performing some calculations. By using narrowing, we refine the type of the argument to a number, which allows us to perform addition without any errors.
Use Case 5: Narrowing with Type Guards
In TypeScript, type guards are functions that return a boolean value, and they can be used to narrow types based on conditions. Type guards can be used to define more complex conditions for narrowing.
For example, let’s assume we have an object that can have a firstName and lastName property, or just a name property. We can use a type guard to narrow the type of the object based on whether it has a firstName and lastName property.
interface Person {
name: string;
firstName?: string;
lastName?: string;
}
function isFullName(person: Person): person is { firstName: string, lastName: string } {
return typeof person.firstName === 'string' && typeof person.lastName === 'string';
}
function greet(person: Person) {
if (isFullName(person)) {
console.log(`Hello ${person.firstName} ${person.lastName}`);
} else {
console.log(`Hello ${person.name}`);
}
}
In the example above, we define an interface for a person object, and a type guard function isFullName that returns a boolean value based on whether the object has a firstName and lastName property. By using narrowing with type guards, we refine the type of the person object based on its actual properties, which allows us to access the properties without any errors.
Conclusion
In conclusion, narrowing is an important feature in TypeScript that can help developers write more robust and error-free code. It allows developers to refine the type of variables and expressions based on conditions, which can catch errors at compile time, improve performance, and make code more readable.
In this article, we explored multiple use cases where narrowing is important in TypeScript, including narrowing with APIs, React components, conditional statements, union types, and type guards. By using narrowing in these scenarios, developers can ensure that their code is more robust, efficient, and maintainable.
💡 Lastly, it’s worth noting that sharing and reusing code components across projects can significantly improve productivity and code quality. Bit is a platform for hosting and sharing reusable components, and it offers seamless integration with TypeScript. With Bit, you can easily create, discover, and use shared components across multiple projects, and leverage the power of TypeScript to ensure type-safety and maintainability. Learn more here and here.
If you loved what you read, you can help me and buy me a cup of coffee?
Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.
Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.
Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:
→ Micro-Frontends
→ Design System
→ Code-Sharing and reuse
→ Monorepo
Learn more:
- How We Build Micro Frontends
- How we Build a Component Design System
- How to reuse React components across your projects
- 5 Ways to Build a React Monorepo
- How to Create a Composable React App with Bit
Refine Your TypeScript Code with Narrowing was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Bits and Pieces - Medium and was authored by Brian Ridolce

Brian Ridolce | Sciencx (2023-03-16T11:27:59+00:00) Refine Your TypeScript Code with Narrowing. Retrieved from https://www.scien.cx/2023/03/16/refine-your-typescript-code-with-narrowing/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.