Skip to content

Commit e820f49

Browse files
committed
Add math intrinsic types
1 parent af027f3 commit e820f49

17 files changed

+1435
-55
lines changed

src/compiler/checker.ts

+133-19
Large diffs are not rendered by default.

src/compiler/types.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -5160,6 +5160,7 @@ namespace ts {
51605160
NonPrimitive = 1 << 26, // intrinsic object type
51615161
TemplateLiteral = 1 << 27, // Template literal type
51625162
StringMapping = 1 << 28, // Uppercase/Lowercase type
5163+
Calculation = 1 << 29, // Math type
51635164

51645165
/* @internal */
51655166
AnyOrUnknown = Any | Unknown,
@@ -5178,7 +5179,7 @@ namespace ts {
51785179
/* @internal */
51795180
Primitive = String | Number | BigInt | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal | UniqueESSymbol,
51805181
StringLike = String | StringLiteral | TemplateLiteral | StringMapping,
5181-
NumberLike = Number | NumberLiteral | Enum,
5182+
NumberLike = Number | NumberLiteral | Enum | Calculation,
51825183
BigIntLike = BigInt | BigIntLiteral,
51835184
BooleanLike = Boolean | BooleanLiteral,
51845185
EnumLike = Enum | EnumLiteral,
@@ -5192,7 +5193,7 @@ namespace ts {
51925193
StructuredType = Object | Union | Intersection,
51935194
TypeVariable = TypeParameter | IndexedAccess,
51945195
InstantiableNonPrimitive = TypeVariable | Conditional | Substitution,
5195-
InstantiablePrimitive = Index | TemplateLiteral | StringMapping,
5196+
InstantiablePrimitive = Index | TemplateLiteral | StringMapping | Calculation,
51965197
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
51975198
StructuredOrInstantiable = StructuredType | Instantiable,
51985199
/* @internal */
@@ -5716,6 +5717,11 @@ namespace ts {
57165717
type: Type;
57175718
}
57185719

5720+
export interface CalculationType extends InstantiableType {
5721+
symbol: Symbol;
5722+
types: [Type] | [Type, Type];
5723+
}
5724+
57195725
// Type parameter substitution (TypeFlags.Substitution)
57205726
// Substitution types are created for type parameters or indexed access types that occur in the
57215727
// true branch of a conditional type. For example, in 'T extends string ? Foo<T> : Bar<T>', the

src/harness/fourslashInterfaceImpl.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,11 @@ namespace FourSlashInterface {
11441144
typeEntry("Lowercase"),
11451145
typeEntry("Capitalize"),
11461146
typeEntry("Uncapitalize"),
1147+
typeEntry("Int"),
1148+
typeEntry("Add"),
1149+
typeEntry("Multiply"),
1150+
typeEntry("LessThan"),
1151+
typeEntry("GreaterThan"),
11471152
interfaceEntry("ThisType"),
11481153
varEntry("ArrayBuffer"),
11491154
interfaceEntry("ArrayBufferTypes"),

src/lib/es5.d.ts

+26
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,32 @@ type Capitalize<S extends string> = intrinsic;
16061606
*/
16071607
type Uncapitalize<S extends string> = intrinsic;
16081608

1609+
/**
1610+
* Convert number literal type to integer
1611+
*/
1612+
type Integer<N extends number> = intrinsic;
1613+
1614+
/**
1615+
* Add two literal numbers
1616+
*/
1617+
type Add<M extends number, N extends number> = intrinsic;
1618+
1619+
/**
1620+
* Multiply two literal numbers
1621+
*/
1622+
type Multiply<M extends number, N extends number> = intrinsic;
1623+
1624+
/**
1625+
* Obtain all members of `A` that are less than `B`
1626+
*/
1627+
type LessThan<A extends number, B extends number> = intrinsic;
1628+
1629+
/**
1630+
* Obtain all members of `A` that are greater than `B`
1631+
*/
1632+
type GreaterThan<A extends number, B extends number> = intrinsic;
1633+
1634+
16091635
/**
16101636
* Marker for contextual 'this' type
16111637
*/

tests/baselines/reference/api/tsserverlibrary.d.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -2607,12 +2607,13 @@ declare namespace ts {
26072607
NonPrimitive = 67108864,
26082608
TemplateLiteral = 134217728,
26092609
StringMapping = 268435456,
2610+
Calculation = 536870912,
26102611
Literal = 2944,
26112612
Unit = 109440,
26122613
StringOrNumberLiteral = 384,
26132614
PossiblyFalsy = 117724,
26142615
StringLike = 402653316,
2615-
NumberLike = 296,
2616+
NumberLike = 536871208,
26162617
BigIntLike = 2112,
26172618
BooleanLike = 528,
26182619
EnumLike = 1056,
@@ -2622,10 +2623,10 @@ declare namespace ts {
26222623
StructuredType = 3670016,
26232624
TypeVariable = 8650752,
26242625
InstantiableNonPrimitive = 58982400,
2625-
InstantiablePrimitive = 406847488,
2626-
Instantiable = 465829888,
2627-
StructuredOrInstantiable = 469499904,
2628-
Narrowable = 536624127,
2626+
InstantiablePrimitive = 943718400,
2627+
Instantiable = 1002700800,
2628+
StructuredOrInstantiable = 1006370816,
2629+
Narrowable = 1073495039,
26292630
}
26302631
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
26312632
export interface Type {
@@ -2787,6 +2788,10 @@ declare namespace ts {
27872788
symbol: Symbol;
27882789
type: Type;
27892790
}
2791+
export interface CalculationType extends InstantiableType {
2792+
symbol: Symbol;
2793+
types: [Type] | [Type, Type];
2794+
}
27902795
export interface SubstitutionType extends InstantiableType {
27912796
objectFlags: ObjectFlags;
27922797
baseType: Type;

tests/baselines/reference/api/typescript.d.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -2607,12 +2607,13 @@ declare namespace ts {
26072607
NonPrimitive = 67108864,
26082608
TemplateLiteral = 134217728,
26092609
StringMapping = 268435456,
2610+
Calculation = 536870912,
26102611
Literal = 2944,
26112612
Unit = 109440,
26122613
StringOrNumberLiteral = 384,
26132614
PossiblyFalsy = 117724,
26142615
StringLike = 402653316,
2615-
NumberLike = 296,
2616+
NumberLike = 536871208,
26162617
BigIntLike = 2112,
26172618
BooleanLike = 528,
26182619
EnumLike = 1056,
@@ -2622,10 +2623,10 @@ declare namespace ts {
26222623
StructuredType = 3670016,
26232624
TypeVariable = 8650752,
26242625
InstantiableNonPrimitive = 58982400,
2625-
InstantiablePrimitive = 406847488,
2626-
Instantiable = 465829888,
2627-
StructuredOrInstantiable = 469499904,
2628-
Narrowable = 536624127,
2626+
InstantiablePrimitive = 943718400,
2627+
Instantiable = 1002700800,
2628+
StructuredOrInstantiable = 1006370816,
2629+
Narrowable = 1073495039,
26292630
}
26302631
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
26312632
export interface Type {
@@ -2787,6 +2788,10 @@ declare namespace ts {
27872788
symbol: Symbol;
27882789
type: Type;
27892790
}
2791+
export interface CalculationType extends InstantiableType {
2792+
symbol: Symbol;
2793+
types: [Type] | [Type, Type];
2794+
}
27902795
export interface SubstitutionType extends InstantiableType {
27912796
objectFlags: ObjectFlags;
27922797
baseType: Type;

tests/baselines/reference/intrinsicTypes.errors.txt

+165-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,28 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(42,5): error TS2322:
88
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322: Type 'Uppercase<T>' is not assignable to type 'Uppercase<U>'.
99
Type 'T' is not assignable to type 'U'.
1010
'T' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint 'string'.
11+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(61,20): error TS2344: Type 'string' does not satisfy the constraint 'number'.
12+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(76,17): error TS2344: Type 'string' does not satisfy the constraint 'number'.
13+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(77,20): error TS2344: Type 'string' does not satisfy the constraint 'number'.
14+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(78,18): error TS2344: Type 'string' does not satisfy the constraint 'number'.
15+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(93,22): error TS2344: Type 'string' does not satisfy the constraint 'number'.
16+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(94,25): error TS2344: Type 'string' does not satisfy the constraint 'number'.
17+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(95,23): error TS2344: Type 'string' does not satisfy the constraint 'number'.
18+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(112,23): error TS2344: Type 'string' does not satisfy the constraint 'number'.
19+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(113,26): error TS2344: Type 'string' does not satisfy the constraint 'number'.
20+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(114,24): error TS2344: Type 'string' does not satisfy the constraint 'number'.
21+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(131,26): error TS2344: Type 'string' does not satisfy the constraint 'number'.
22+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(132,29): error TS2344: Type 'string' does not satisfy the constraint 'number'.
23+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(133,27): error TS2344: Type 'string' does not satisfy the constraint 'number'.
24+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(149,5): error TS2322: Type 'number' is not assignable to type 'Add<T, U>'.
25+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(150,5): error TS2322: Type 'Multiply<T, U>' is not assignable to type 'Add<T, U>'.
26+
Type 'number' is not assignable to type 'Add<T, U>'.
27+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(151,5): error TS2322: Type 'number' is not assignable to type 'Multiply<T, U>'.
28+
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(152,5): error TS2322: Type 'Add<T, U>' is not assignable to type 'Multiply<T, U>'.
29+
Type 'number' is not assignable to type 'Multiply<T, U>'.
1130

1231

13-
==== tests/cases/conformance/types/typeAliases/intrinsicTypes.ts (8 errors) ====
32+
==== tests/cases/conformance/types/typeAliases/intrinsicTypes.ts (25 errors) ====
1433
type TU1 = Uppercase<'hello'>; // "HELLO"
1534
type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
1635
type TU3 = Uppercase<string>; // string
@@ -83,4 +102,149 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322:
83102
function foo4<U extends string>(x: Uppercase<U>) {
84103
return foo3(x);
85104
}
105+
106+
type TI1 = Integer<3.5>; // 3
107+
type TI2 = Integer<2.5 | 3.4>; // 2 | 3
108+
type TI3 = Integer<number>; // number
109+
type TI4 = Integer<any>; // any
110+
type TI5 = Integer<never>; // never
111+
type TI6 = Integer<'42'>; // Error
112+
~~~~
113+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
114+
115+
type TA1 = Add<4, 2>; // 6
116+
type TA2L = Add<4 | 5, 2>; // 6 | 7
117+
type TA2R = Add<4, 2 | 3>; // 6 | 7
118+
type TA2LR = Add<4 | 5, 2 | 3>; // 6 | 7 | 8
119+
type TA3L = Add<number, 2>; // number
120+
type TA3R = Add<4, number>; // number
121+
type TA3LR = Add<number, number>; // number
122+
type TA4L = Add<any, 2>; // any
123+
type TA4R = Add<4, any>; // any
124+
type TA4LR = Add<any, any>; // any
125+
type TA5L = Add<never, 2>; // never
126+
type TA5R = Add<4, never>; // never
127+
type TA5LR = Add<never, never>; // never
128+
type TA6L = Add<'4', 2>; // Error
129+
~~~
130+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
131+
type TA6R = Add<4, '2'>; // Error
132+
~~~
133+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
134+
type TA6LR = Add<'4', '2'>; // Error
135+
~~~
136+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
137+
138+
type TM1 = Multiply<4, 2>; // 8
139+
type TM2L = Multiply<4 | 5, 2>; // 8 | 10
140+
type TM2R = Multiply<4, 2 | 3>; // 8 | 12
141+
type TM2LR = Multiply<4 | 5, 2 | 3>; // 8 | 12 | 10 | 15
142+
type TM3L = Multiply<number, 2>; // number
143+
type TM3R = Multiply<4, number>; // number
144+
type TM3LR = Multiply<number, number>; // number
145+
type TM4L = Multiply<any, 2>; // any
146+
type TM4R = Multiply<4, any>; // any
147+
type TM4LR = Multiply<any, any>; // any
148+
type TM5L = Multiply<never, 2>; // never
149+
type TM5R = Multiply<4, never>; // never
150+
type TM5LR = Multiply<never, never>; // never
151+
type TM6L = Multiply<'4', 2>; // Error
152+
~~~
153+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
154+
type TM6R = Multiply<4, '2'>; // Error
155+
~~~
156+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
157+
type TM6LR = Multiply<'4', '2'>; // Error
158+
~~~
159+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
160+
161+
type TLT1GT = LessThan<4, 2>; // never
162+
type TLT1LT = LessThan<2, 4>; // 2
163+
type TLT1EQ = LessThan<4, 4>; // never
164+
type TLT2L = LessThan<1 | 2 | 3, 2>; // 1
165+
type TLT2R = LessThan<2, 1 | 2 | 3>; // 2
166+
type TLT2LR = LessThan<1 | 2, 1 | 2 | 3>; // 1 | 2
167+
type TLT3L = LessThan<number, 2>; // number
168+
type TLT3R = LessThan<4, number>; // number
169+
type TLT3LR = LessThan<number, number>; // number
170+
type TLT4L = LessThan<any, 2>; // any
171+
type TLT4R = LessThan<4, any>; // any
172+
type TLT4LR = LessThan<any, any>; // any
173+
type TLT5L = LessThan<never, 2>; // never
174+
type TLT5R = LessThan<4, never>; // never
175+
type TLT5LR = LessThan<never, never>; // never
176+
type TLT6L = LessThan<'4', 2>; // Error
177+
~~~
178+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
179+
type TLT6R = LessThan<4, '2'>; // Error
180+
~~~
181+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
182+
type TLT6LR = LessThan<'4', '2'>; // Error
183+
~~~
184+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
185+
186+
type TGT1GT = GreaterThan<4, 2>; // 4
187+
type TGT1LT = GreaterThan<2, 4>; // never
188+
type TGT1EQ = GreaterThan<4, 4>; // never
189+
type TGT2L = GreaterThan<1 | 2 | 3, 2>; // 3
190+
type TGT2R = GreaterThan<2, 1 | 2 | 3>; // 2
191+
type TGT2LR = GreaterThan<1 | 2, 1 | 2 | 3>; // 2
192+
type TGT3L = GreaterThan<number, 2>; // number
193+
type TGT3R = GreaterThan<4, number>; // number
194+
type TGT3LR = GreaterThan<number, number>; // number
195+
type TGT4L = GreaterThan<any, 2>; // any
196+
type TGT4R = GreaterThan<4, any>; // any
197+
type TGT4LR = GreaterThan<any, any>; // any
198+
type TGT5L = GreaterThan<never, 2>; // never
199+
type TGT5R = GreaterThan<4, never>; // never
200+
type TGT5LR = GreaterThan<never, never>; // never
201+
type TGT6L = GreaterThan<'4', 2>; // Error
202+
~~~
203+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
204+
type TGT6R = GreaterThan<4, '2'>; // Error
205+
~~~
206+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
207+
type TGT6LR = GreaterThan<'4', '2'>; // Error
208+
~~~
209+
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
210+
211+
type TIX1<S extends number> = Integer<S>;
212+
type TIX2 = TIX1<4.2>; // 4
213+
type TAX1<M extends number, N extends number> = Add<M, N>;
214+
type TAX2 = TAX1<4, 2>; // 6
215+
type TMX1<M extends number, N extends number> = Multiply<M, N>;
216+
type TMX2 = TMX1<4, 2>; // 8
217+
type TLTX1<M extends number, N extends number> = LessThan<M, N>;
218+
type TLTX2 = TLTX1<2, 4>; // 2
219+
type TLTX3 = TLTX1<5, 4>; // never
220+
type TAMX = Add<2, Multiply<5, 8>> // 42
221+
222+
function foo5<T extends number, U extends T>(s: number, x: Add<T, U>, y: Multiply<T, U>) {
223+
s = x;
224+
s = y;
225+
x = s; // Error
226+
~
227+
!!! error TS2322: Type 'number' is not assignable to type 'Add<T, U>'.
228+
x = y; // Error
229+
~
230+
!!! error TS2322: Type 'Multiply<T, U>' is not assignable to type 'Add<T, U>'.
231+
!!! error TS2322: Type 'number' is not assignable to type 'Add<T, U>'.
232+
y = s; // Error
233+
~
234+
!!! error TS2322: Type 'number' is not assignable to type 'Multiply<T, U>'.
235+
y = x; // Error
236+
~
237+
!!! error TS2322: Type 'Add<T, U>' is not assignable to type 'Multiply<T, U>'.
238+
!!! error TS2322: Type 'number' is not assignable to type 'Multiply<T, U>'.
239+
}
240+
241+
function foo6<T extends 0 | 1>(x: Add<T, 3>) {
242+
let s: 3 | 4 = x;
243+
}
244+
245+
declare function foo7<T extends number>(x: Integer<T>): T;
246+
247+
function foo8<U extends number>(x: Integer<U>) {
248+
return foo7(x);
249+
}
86250

0 commit comments

Comments
 (0)