This feature request is similar to units of measure in F#.
For example:
constmetres=125<m>;constseconds=2<s>;letspeed: number<m/s>;speed=metres/seconds;// validspeed=metres/seconds/10<s>;// error -- cannot convert m/s**2 to m/s
(Moved from work item 1715 on Codeplex.)
Proposal
Last Updated: 2016-06-09
Copied from:https://github.com/dsherret/Units-of-Measure-Proposal-for-TypeScript
Overview
Units of measure is a useful F# feature that provides the optional ability to create tighter constraints on numbers.
TypeScript could benefit from a similar feature that would add zero runtime overhead, increase type constraints, and help decrease programmer error when doing mathematical calculations that involve units. The feature should prefer explicity.
Defining Units of Measure
Units of measure should probably use syntax similar to type aliases (#957). More discussion is needed on this, but for the purpose of this document it will use the following syntax:
typemeasure<name>[=measureexpression];
The optional measure expression part can be used to define a new measures in terms of previously defined measures.
Example Definitions
typemeasurem;typemeasures;typemeasurea=m/s**2;
Units of measure can be defined in any order. For example, a in the example above could have been defined before m or s.
Circular Definitions
Circular definitions are NOT allowed. For example:
typemeasurea=b;typemeasureb=a;// error
Use with Number
Units of measure can be defined on a number type in any of the following ways:
typemeasurem;// 1. Explicitlyletdistance: number<m>=12<m>;// 2. Implictlyletdistance=12<m>;// 3. Using Number classletdistance=newNumber(10)<s>;
TODO: Maybe we shouldn't use the <m> syntax because it might conflict with jsx files.
Detailed Full Example
typemeasurem;typemeasures;typemeasurea=m/s**2;letacceleration=12<a>,time=10<s>;letdistance=1/2*acceleration*(time**2);// valid -- implicitly typed to number<m>letavgSpeed=distance/time;// valid -- implicitly typed to number<m/s>time+=5<s>;// validtime+=5;// error -- cannot convert number to number<s>time+=distance;// error -- cannot convert number<m> to number<s>// converting to another unit requires asserting to number then the measuretime+=(distanceasnumber)<s>;// validacceleration+=12<m/s**2>;// validacceleration+=10<a>;// validacceleration+=12<m/s**2>*10<s>;// error -- cannot convert number<m/s> to number<a>
Use With Non-Unit of Measure Number Types
Sometimes previously written code or external libraries will return number types without a unit of measure. In these cases, it is useful to allow the programmer to specify the unit like so:
typemeasures;lettime=3<s>;time+=MyOldLibrary.getSeconds();// error -- type 'number' is not assignable to type 'number<s>'time+=MyOldLibrary.getSeconds()<s>;// valid
Dimensionless Unit
A dimensionless unit is a unit of measure defined as number<1>.
letratio=10<s>/20<s>;// implicitly typed to number<1>lettime: number<s>;time=2<s>*ratio;// validtime=time/ratio;// validtime=(ratioasnumber)<s>;// validtime=2<s>+ratio;// error, cannot assign number<1> to number<s>time=ratio;// error, cannot assign number<1> to number<s>time=ratio<s>;// error, cannot assert number<1> to number<s>
Scope
Works the same way as type.
External and Internal Modules
Also works the same way as type.
In addition, if an external library has a definition for meters and another external library has a definition for meters then they should be able to be linked together by doing:
import{masmathLibraryMeterType}from"my-math-library";import{masmathOtherLibraryMeterType}from"my-other-math-library";typemeasurem=mathLibraryMeterType|mathOtherLibraryMeterType;TODO: The above needs more thought though.
Definition File
Units of measure can be defined in TypeScript definition files ( .d.ts) and can be used by any file that references it. Defining units of measure in a definition file is done just the same as defining one in a .ts file.
Compilation
The units of measure feature will not create any runtime overhead. For example:
typemeasurecm;typemeasurem;letmetersToCentimeters=100<cm/m>;letlength: number<cm>=20<m>*metersToCentimeters;
Compiles to the following JavaScript:
varmetersToCentimeters=100;varlength=20*metersToCentimeters;
Math Library
Units of measure should work well with the current existing Math object.
Some examples:
Math.min(0<s>,4<m>);// error, cannot mix number<s> with number<m> -- todo: How would this constraint be defined?letvolume=Math.pow(2<m>,3)<m**3>;letlength=Math.sqrt(4<m^2>)<m>;
This feature request is similar to units of measure in F#.
For example:
(Moved from work item 1715 on Codeplex.)
Proposal
Last Updated: 2016-06-09
Copied from:https://github.com/dsherret/Units-of-Measure-Proposal-for-TypeScript
Overview
Units of measure is a useful F# feature that provides the optional ability to create tighter constraints on numbers.
TypeScript could benefit from a similar feature that would add zero runtime overhead, increase type constraints, and help decrease programmer error when doing mathematical calculations that involve units. The feature should prefer explicity.
Defining Units of Measure
Units of measure should probably use syntax similar to type aliases (#957). More discussion is needed on this, but for the purpose of this document it will use the following syntax:
The optional measure expression part can be used to define a new measures in terms of previously defined measures.
Example Definitions
Units of measure can be defined in any order. For example,
ain the example above could have been defined beforemors.Circular Definitions
Circular definitions are NOT allowed. For example:
Use with Number
Units of measure can be defined on a number type in any of the following ways:
TODO: Maybe we shouldn't use the
<m>syntax because it might conflict with jsx files.Detailed Full Example
Use With Non-Unit of Measure Number Types
Sometimes previously written code or external libraries will return number types without a unit of measure. In these cases, it is useful to allow the programmer to specify the unit like so:
Dimensionless Unit
A dimensionless unit is a unit of measure defined as
number<1>.Scope
Works the same way as
type.External and Internal Modules
Also works the same way as
type.In addition, if an external library has a definition for meters and another external library has a definition for meters then they should be able to be linked together by doing:
TODO: The above needs more thought though.
Definition File
Units of measure can be defined in TypeScript definition files (
.d.ts) and can be used by any file that references it. Defining units of measure in a definition file is done just the same as defining one in a.tsfile.Compilation
The units of measure feature will not create any runtime overhead. For example:
Compiles to the following JavaScript:
Math Library
Units of measure should work well with the current existing Math object.
Some examples: