In the Typescript zoo, there are union types that are very helpful, specifically to narrow down strings :
type size = 'small' | 'medium' | 'large';
This works well for known list of items, but for other types, one often use the common type string
.
Could we do better ? Why should we do better ?
Let's start with some data :
{
const madrid: string = 'Madrid';
const spain: string = 'Spain';
const localisation = spain;
}
It's not clear whether the localisation
has to be a city or a country, so let's try to define some type :
{
type City = string
const madrid: City = 'Madrid';
type Country = string;
const spain: Country = 'Spain';
const localisation: Country = spain;
const localisation2: Country = madrid; // 😵 oh no !!!
// it passes...
// well, Madrid is not a Country !
}
Above, defining a type City
doesn't help ; Typescript just takes this type as an alias to string
, therefore it won't enforce anything, except our intention (that makes the answer to the question : why should we do better ?)
Could we do better ? Yes : even if you have an open list of values, you may define a type by examples :
{
type City = 'London' | 'Paris' | '[any city]'
const madrid: City = 'Madrid' as City;
type Country = 'United-Kingdom' | 'France' | '[any country]';
const spain: Country = 'Spain' as Country;
const localisation: Country = spain;
const localisation2: Country = madrid; // ❌ oh yes, it fails !!!
// Typescript will say that a City
// is not assignable to a Country
}
What is nice, is that your code can either take any data source with valid types as well as hard-coded data like in the example above : writing 'Spain' as Country
makes sense, 'Spain' as City
wouldn't.
This is a technique that I use and abuse because it prevents putting a string in another string when they are semantically unrelated. And believe me, it saves me from lots of runtime errors !
And it works for numbers too :
/** Any HTTP port (other values are accepted
* as long they are related to HTTP)
*/
type HttpPort = 80 | 8080 | 443 | 8443;
const port1: HttpPort = 8080; // ok, a known value
const port2: HttpPort = 8888 as HttpPort; // because I'm sure
Top comments (0)