Say I have two types of numbers that I\'m tracking like latitude
and longitude
. I would like to represent these variables with the basic num
Here is a simple way to achieve this:
You only need two functions, one that converts a number to a number type and one for the reverse process. Here are the two functions:
module NumberType {
/**
* Use this function to convert to a number type from a number primitive.
* @param n a number primitive
* @returns a number type that represents the number primitive
*/
export function to(n : number) : T {
return ( n);
}
/**
* Use this function to convert a number type back to a number primitive.
* @param nt a number type
* @returns the number primitive that is represented by the number type
*/
export function from(nt : T) : number {
return ( nt);
}
}
You can create your own number type like so:
interface LatitudeNumber extends Number {
// some property to structurally differentiate MyIdentifier
// from other number types is needed due to typescript's structural
// typing. Since this is an interface I suggest you reuse the name
// of the interface, like so:
LatitudeNumber;
}
Here is an example of how LatitudeNumber can be used
function doArithmeticAndLog(lat : LatitudeNumber) {
console.log(NumberType.from(lat) * 2);
}
doArithmeticAndLog(NumberType.to(100));
This will log 200
to the console.
As you'd expect, this function can not be called with number primitives nor other number types:
interface LongitudeNumber extends Number {
LongitudeNumber;
}
doArithmeticAndLog(2); // compile error: (number != LongitudeNumber)
doArithmeticAndLog(NumberType.to(2)); // compile error: LongitudeNumer != LatitudeNumber
What this does is simply fool Typescript into believing a primitive number is really some extension of the Number interface (what I call a number type), while actually the primitive number is never converted to an actual object that implements the number type. Conversion is not necessary since the number type behaves like a primitive number type; a number type simply is a number primitive.
The trick is simply casting to any
, so that typescript stops type checking. So the above code can be rewritten to:
function doArithmeticAndLog(lat : LatitudeNumber) {
console.log( lat * 2);
}
doArithmeticAndLog(100);
As you can see the function calls are not even really necessary, because a number and its number type can be used interchangeably. This means absolutely zero performance or memory loss needs to be incurred at run-time. I'd still strongly advise to use the function calls, since a function call costs close to nothing and by casting to any
yourself you loose type safety (e.g doArithmeticAndLog(
will compile, but will result in a NaN logged to the console at run-time)... But if you want full performance you may use this trick.
It can also work for other primitive like string and boolean.
Happy typing!