You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+97-51Lines changed: 97 additions & 51 deletions
Original file line number
Diff line number
Diff line change
@@ -7,101 +7,147 @@ Units of Measure: Proposal for TypeScript
7
7
8
8
Units of measure is a useful [F# feature](http://msdn.microsoft.com/en-us/library/dd233243.aspx) that provides the optional ability to create tighter constraints on floating point and signed integer values.
9
9
10
-
TypeScript could benefit from a similar units of measure feature and expand to include tiny type support for `string`, `boolean`, and `date` objects. Such a feature would add zero runtime overhead, increase type constraints, and help decrease programmer error.
10
+
TypeScript could benefit from a similar units of measure feature. Such a feature would add zero runtime overhead, increase type constraints, and help decrease programmer error.
The optional measure part can be used to define a new types in terms of previously defined types. Note that this composite type cannot be used with non-`number` types.
20
+
The optional unit part can be used to define a new unit in terms of previously defined units.
21
21
22
-
**Examples:**
22
+
The `<unit-name>` is unique so there cannot be any other types or variables defined with the same name within the unit's scope. For example, the following would not be valid:
23
23
24
24
```typescript
25
-
typem extends number;
26
-
types extends number;
27
-
typea=m/s^2;
28
-
typeemail extends string;
25
+
var m =10;
26
+
27
+
unitm; // error
28
+
```
29
+
30
+
### Example Definitions
31
+
32
+
```typescript
33
+
unitm;
34
+
units;
35
+
unita=m/s^2;
29
36
```
30
37
31
38
Note: The caret symbol does not denote a bitwise XOR operator, but rather an exponent. In this case, `m/s^2` is equivalent to `m/s/s`.
32
39
33
-
## Use with Number
40
+
### Circular Definitions
41
+
42
+
Circular definitions are NOT allowed. For example:
43
+
44
+
```typescript
45
+
unita=b/c;
46
+
unitb=a*c;
47
+
unitc=b/a;
48
+
```
49
+
50
+
## Using units
34
51
35
52
```typescript
36
-
typem extends number;
37
-
types extends number;
38
-
typea=m/s^2;
53
+
unitm;
54
+
units;
55
+
unita=m/s^2;
39
56
40
57
var acceleration =12<a>,
41
-
time =10<s>;
58
+
time =newNumber(10)<s>;
42
59
43
60
var distance =1/2*acceleration*time*time; // valid -- implicitly typed to number<m>
44
61
var avgSpeed =distance/time; // valid -- implicitly typed to number<m/s>
45
62
46
63
time+=5<s>; // valid
47
-
time+=5; //compile error -- Cannot convert number to number<s>
48
-
time+=distance; //compile error -- Cannot convert number<m> to number<s>
64
+
time+=5; // error -- cannot convert number to number<s>
65
+
time+=distance; // error -- cannot convert number<m> to number<s>
49
66
50
67
acceleration+=12<m/s^2>; // valid
51
68
acceleration+=10<a>; // valid
52
-
acceleration+=12<m/s^2>*10<s>; //compile error -- Cannot convert number<m/s> to number<a>
69
+
acceleration+=12<m/s^2>*10<s>; // error -- cannot convert number<m/s> to number<a>
53
70
```
54
71
55
-
## Use with String, Boolean, and Date
72
+
###Use With Non-Unit of Measure Number Types
56
73
57
-
```typescript
58
-
typeemail extends string;
74
+
Sometimes legacy 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:
59
75
60
-
function sendEmail(email:string<email>, message:string) {
time=time+num; // error -- cannot add number to number<s>
83
+
time=time+num<s>; // valid
67
84
```
68
85
69
-
The following is invalid:
86
+
## Dimensionless Unit
87
+
88
+
A dimensionless unit is a unit of measure defined as `number<1>`.
70
89
71
90
```typescript
72
-
typem extends number;
73
-
types extends number;
74
-
typea=m/s^2;
91
+
var ratio =10<s>/20<s>, // implicitly typed to number<1>
92
+
time :number<s>;
75
93
76
-
var myString :string<a>; // compile error -- Cannot use number types with a string
94
+
time=2<s>*ratio;
95
+
time*=ratio;
96
+
time=2<s>+ratio; // error, cannot add number<1> to number<s>
97
+
time=ratio; // error, cannot assign number<1> to number<s>
77
98
```
78
99
79
-
## Additional Cases
100
+
## Math Library
101
+
102
+
Units of measure should work well with the current existing [Math object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math).
103
+
104
+
Some examples:
80
105
81
106
```typescript
82
-
typem extends number;
83
-
typeemail extends string;
84
-
typestartDate extends Date;
85
-
typeflag extends boolean;
86
-
87
-
var num =newNumber<m>(),
88
-
str =newString<email>(),
89
-
date =newDate<startDate>(),
90
-
b =newBoolean<flag>();
107
+
Math.min(0<s>, 4<m>); // error, cannot mix number<s> with number<m>
108
+
109
+
var volume =Math.pow(2<m>, 3); // volume is implicitly typed to number<m^3>
91
110
```
92
111
93
-
## Additional Considerations
112
+
## Outstanding Questions
113
+
114
+
As discussed in [this thread](https://github.com/Microsoft/TypeScript/issues/364#issuecomment-51720786).
115
+
116
+
### 1. How does units of measure work when used across modules?
117
+
118
+
#### Suggestion #1
94
119
95
-
The defintion statement could also be like one of the following (or a combination of):
120
+
> A measure is in the scope of a module. Outside the module it is not visible. When using external modules, you should create measures in a .d.ts file.
> Just throwing out some ideas here, but maybe measures could be imported in order to prevent conflicts between libraries... so you would have to write something like `import unit m = MyMeasureModule.m;` at the top of each file you want to use it. Then when you're writing a measure in a module you would do this:
96
127
97
128
```typescript
98
-
typestring<email>;
99
-
declaretypeemail : string;
129
+
moduleMyModule {
130
+
exportunitm; // or maybe these could also be defined at the class level
131
+
exportunits;
132
+
133
+
exportclassMyClass {
134
+
myMethod() :number<m/s> {
135
+
return20<m/s>;
136
+
}
137
+
}
138
+
}
100
139
```
101
140
102
-
## Supported Types
141
+
> That could help prevent conflicts because you could do `import unit m = MyMeasureModule.m` and `import unit meters = SomeOtherLibrary.m`, but it wouldn't be so nice when a conflict occurs. Additionally, it wouldn't be that nice to have to rewrite measure statements at the top of each file you want to use them in, but I guess it's not too bad (think of it like the necessity of writing using statements in c#).
0 commit comments