TypeScript Best Practices #2 – Use More Precise Type Than ‘string’
Introduction
The best thing about typescript is that you can always start by using just the basic features of the language. You don't have to use every advanced feature of it right from the beginning. You can incrementally learn and implement stricter typescript checks.
Defining a type
To get started, let's take an example. You can define the TypeScript type for product_1
as Object
const product_1: Object = {
name: "MacBook Pro",
color: 'grey',
dateOfManufacture: '07-09-2021'
}
This is a valid TypeScript code. However, it doesn't help you much (other than giving you the satisfaction of adding the type for this variable). For better type checking, it would be better to define an interface for product_1
.
interface IProduct {
name: string;
color: string;
dateOfManufacture: string;
}
const product_1: IProduct = {
name: "MacBook Pro",
color: 'grey',
dateOfManufacture: '07-09-2021'
}
This looks much better. Using the interface IProduct
ensures that you (or someone on your team) doesn't accidentally assign any value that doesn't conform to IProduct
.
For example, in the below code, the value of color
property is set as 0
. This would result in a typescript error.
const product_1: IProduct = {
name: "MacBook Pro",
color: 0, // ~~ Type 'number' is not assignable to type 'string'
dateOfManufacture: '07-09-2021'
}
Now, if you have ever taken the Introduction of Algorithms
class, you might have
guessed the question you would ask yourself every time you have a naive solution.
Can I do better?
But before that, let's see why you would want to do better.
So consider the below code snippet.
const product_1: IProduct = {
name: "MacBook Pro",
color: 'greyy',
dateOfManufacture: '07-09-2021'
}
Again, this is a valid typescript code. product_1
is an object containing all the mandatory properties having values of the correct type i.e. string
. However, there is something wrong here. By mistake, the developer spelled the color grey
as greyy
(an extra y
in end). And that's okay. It happens!
Now, the question is can you write better typescript code to catch such errors before you run the code? Well, the answer is a big YES!
There are two ways to solve this.
Option 1: Use a union type
You can define a union type that would allow only a few specific values. Since Union type would be very specific about what values it can accept, typescript would be able to do more thorough checking.
type colorType = 'grey' | 'white' | 'rose gold';
interface IProduct {
name: string;
color: colorType;
dateOfManufacture: string;
}
With union type in place, if you mistyped the spelling of the color
property it would result in an error as shown below.
const product_1: IProduct = {
name: "MacBook Pro",
color: 'greyy', // ~~ Type '"greyy"' is not assignable to type 'colorType'
dateOfManufacture: '07-09-2021'
}
Option 2: Define an enum
You can define an enum with all the possible values. The best thing about enums in typescript is that you can use it both as a type
and as a value
.
So you can define the enum COLORS
like below and use it as a type in the interface IProduct
enum COLORS {
GREY = 'grey',
WHITE = 'white',
ROSE_GOLD = 'rose gold'
}
interface IProduct {
name: string;
color: COLORS;
dateOfManufacture: string;
}
In this approach, since you have defined the type of color
as COLORS
, you'll use the enum in the value as well. Directly using the string grey
would also throw an error.
const product_1: IProduct = {
name: "MacBook Pro",
color: COLORS.GREY,
dateOfManufacture: '07-09-2021'
}
Conclusion
In this article, we discussed that the domain of the values that a string
type can accept, is huge. Whenever you have a variable of type string, you should ask yourself if you can use a narrower type than string
. If it is possible, you can use any of the two options discussed above and ensure that you (and your colleagues) catch such potential bugs earlier during the development cycle.
Thank you for reading, hope you found this useful. Let me know in the comments below.
Happy coding!