Skip to content

Commit 6576198

Browse files
skeatekungfooman
andcommittedJun 1, 2024
Add math intrinsic types
Co-authored-by: kungfooman <lama12345@gmail.com>
1 parent ef514af commit 6576198

15 files changed

+2046
-823
lines changed
 

‎src/compiler/checker.ts

+177-26
Large diffs are not rendered by default.

‎src/compiler/types.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -6222,6 +6222,7 @@ export const enum TypeFlags {
62226222
Reserved1 = 1 << 29, // Used by union/intersection type construction
62236223
/** @internal */
62246224
Reserved2 = 1 << 30, // Used by union/intersection type construction
6225+
Calculation = 1 << 31, // Math type
62256226

62266227
/** @internal */
62276228
AnyOrUnknown = Any | Unknown,
@@ -6239,7 +6240,7 @@ export const enum TypeFlags {
62396240
/** @internal */
62406241
Intrinsic = Any | Unknown | String | Number | BigInt | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
62416242
StringLike = String | StringLiteral | TemplateLiteral | StringMapping,
6242-
NumberLike = Number | NumberLiteral | Enum,
6243+
NumberLike = Number | NumberLiteral | Enum | Calculation,
62436244
BigIntLike = BigInt | BigIntLiteral,
62446245
BooleanLike = Boolean | BooleanLiteral,
62456246
EnumLike = Enum | EnumLiteral,
@@ -6255,7 +6256,7 @@ export const enum TypeFlags {
62556256
StructuredType = Object | Union | Intersection,
62566257
TypeVariable = TypeParameter | IndexedAccess,
62576258
InstantiableNonPrimitive = TypeVariable | Conditional | Substitution,
6258-
InstantiablePrimitive = Index | TemplateLiteral | StringMapping,
6259+
InstantiablePrimitive = Index | TemplateLiteral | StringMapping | Calculation,
62596260
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
62606261
StructuredOrInstantiable = StructuredType | Instantiable,
62616262
/** @internal */
@@ -6826,6 +6827,11 @@ export interface StringMappingType extends InstantiableType {
68266827
type: Type;
68276828
}
68286829

6830+
export interface CalculationType extends InstantiableType {
6831+
symbol: Symbol;
6832+
types: [Type] | [Type, Type];
6833+
}
6834+
68296835
// Type parameter substitution (TypeFlags.Substitution)
68306836
// Substitution types are created for type parameters or indexed access types that occur in the
68316837
// 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
@@ -1209,6 +1209,11 @@ export namespace Completion {
12091209
typeEntry("Lowercase"),
12101210
typeEntry("Capitalize"),
12111211
typeEntry("Uncapitalize"),
1212+
typeEntry("Integer"),
1213+
typeEntry("Add"),
1214+
typeEntry("Subtract"),
1215+
typeEntry("Multiply"),
1216+
typeEntry("Divide"),
12121217
typeEntry("NoInfer"),
12131218
interfaceEntry("ThisType"),
12141219
varEntry("ArrayBuffer"),

‎src/lib/es5.d.ts

+25
Original file line numberDiff line numberDiff line change
@@ -1649,6 +1649,31 @@ type Capitalize<S extends string> = intrinsic;
16491649
*/
16501650
type Uncapitalize<S extends string> = intrinsic;
16511651

1652+
/**
1653+
* Convert number literal type to integer
1654+
*/
1655+
type Integer<N extends number> = intrinsic;
1656+
1657+
/**
1658+
* Add two literal numbers
1659+
*/
1660+
type Add<M extends number, N extends number> = intrinsic;
1661+
1662+
/**
1663+
* Subtract two literal numbers
1664+
*/
1665+
type Subtract<M extends number, N extends number> = intrinsic;
1666+
1667+
/**
1668+
* Multiply two literal numbers
1669+
*/
1670+
type Multiply<M extends number, N extends number> = intrinsic;
1671+
1672+
/**
1673+
* Divide two literal numbers
1674+
*/
1675+
type Divide<M extends number, N extends number> = intrinsic;
1676+
16521677
/**
16531678
* Marker for non-inference type position
16541679
*/

‎tests/baselines/reference/intrinsicTypes.errors.txt

-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ intrinsicTypes.ts(43,5): error TS2322: Type 'Uppercase<T>' is not assignable to
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'.
1111

12-
13-
==== intrinsicTypes.ts (8 errors) ====
1412
type TU1 = Uppercase<'hello'>; // "HELLO"
1513
type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
1614
type TU3 = Uppercase<string>; // Uppercase<string>

‎tests/baselines/reference/intrinsicTypes.js

+207
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,113 @@ declare function foo3<T extends string>(x: Uppercase<T>): T;
5555
function foo4<U extends string>(x: Uppercase<U>) {
5656
return foo3(x);
5757
}
58+
59+
type TI1 = Integer<3.5>; // 3
60+
type TI2 = Integer<2.5 | 3.4>; // 2 | 3
61+
type TI3 = Integer<number>; // number
62+
type TI4 = Integer<any>; // any
63+
type TI5 = Integer<never>; // never
64+
type TI6 = Integer<'42'>; // Error
65+
66+
type TA1 = Add<4, 2>; // 6
67+
type TA2L = Add<4 | 5, 2>; // 6 | 7
68+
type TA2R = Add<4, 2 | 3>; // 6 | 7
69+
type TA2LR = Add<4 | 5, 2 | 3>; // 6 | 7 | 8
70+
type TA3L = Add<number, 2>; // number
71+
type TA3R = Add<4, number>; // number
72+
type TA3LR = Add<number, number>; // number
73+
type TA4L = Add<any, 2>; // any
74+
type TA4R = Add<4, any>; // any
75+
type TA4LR = Add<any, any>; // any
76+
type TA5L = Add<never, 2>; // never
77+
type TA5R = Add<4, never>; // never
78+
type TA5LR = Add<never, never>; // never
79+
type TA6L = Add<'4', 2>; // Error
80+
type TA6R = Add<4, '2'>; // Error
81+
type TA6LR = Add<'4', '2'>; // Error
82+
83+
type TS1 = Subtract<4, 2>; // 2
84+
type TS2L = Subtract<4 | 5, 2>; // 2 | 3
85+
type TS2R = Subtract<4, 2 | 3>; // 2 | 1
86+
type TS2LR = Subtract<4 | 5, 2 | 3>; // 2 | 1 | 3
87+
type TS3L = Subtract<number, 2>; // number
88+
type TS3R = Subtract<4, number>; // number
89+
type TS3LR = Subtract<number, number>; // number
90+
type TS4L = Subtract<any, 2>; // any
91+
type TS4R = Subtract<4, any>; // any
92+
type TS4LR = Subtract<any, any>; // any
93+
type TS5L = Subtract<never, 2>; // never
94+
type TS5R = Subtract<4, never>; // never
95+
type TS5LR = Subtract<never, never>; // never
96+
type TS6L = Subtract<'4', 2>; // Error
97+
type TS6R = Subtract<4, '2'>; // Error
98+
type TS6LR = Subtract<'4', '2'>; // Error
99+
100+
type TM1 = Multiply<4, 2>; // 8
101+
type TM2L = Multiply<4 | 5, 2>; // 8 | 10
102+
type TM2R = Multiply<4, 2 | 3>; // 8 | 12
103+
type TM2LR = Multiply<4 | 5, 2 | 3>; // 8 | 12 | 10 | 15
104+
type TM3L = Multiply<number, 2>; // number
105+
type TM3R = Multiply<4, number>; // number
106+
type TM3LR = Multiply<number, number>; // number
107+
type TM4L = Multiply<any, 2>; // any
108+
type TM4R = Multiply<4, any>; // any
109+
type TM4LR = Multiply<any, any>; // any
110+
type TM5L = Multiply<never, 2>; // never
111+
type TM5R = Multiply<4, never>; // never
112+
type TM5LR = Multiply<never, never>; // never
113+
type TM6L = Multiply<'4', 2>; // Error
114+
type TM6R = Multiply<4, '2'>; // Error
115+
type TM6LR = Multiply<'4', '2'>; // Error
116+
117+
type TD1 = Divide<4, 2>; // 2
118+
type TD2L = Divide<4 | 5, 2>; // 2 | 2.5
119+
type TD2R = Divide<4, 2 | 4>; // 2 | 1
120+
type TD2LR = Divide<4 | 5, 2 | 4>; // 2 | 1 | 2.5 | 1.25
121+
type TD3L = Divide<number, 2>; // number
122+
type TD3R = Divide<4, number>; // number
123+
type TD3LR = Divide<number, number>; // number
124+
type TD4L = Divide<any, 2>; // any
125+
type TD4R = Divide<4, any>; // any
126+
type TD4LR = Divide<any, any>; // any
127+
type TD5L = Divide<never, 2>; // never
128+
type TD5R = Divide<4, never>; // never
129+
type TD5LR = Divide<never, never>; // never
130+
type TD6L = Divide<'4', 2>; // Error
131+
type TD6R = Divide<4, '2'>; // Error
132+
type TD6LR = Divide<'4', '2'>; // Error
133+
type TD7 = Divide<1, 0>; // never
134+
135+
type TIX1<S extends number> = Integer<S>;
136+
type TIX2 = TIX1<4.2>; // 4
137+
type TAX1<M extends number, N extends number> = Add<M, N>;
138+
type TAX2 = TAX1<4, 2>; // 6
139+
type TSX1<M extends number, N extends number> = Subtract<M, N>;
140+
type TSX2 = TSX1<4, 2>; // 6
141+
type TMX1<M extends number, N extends number> = Multiply<M, N>;
142+
type TMX2 = TMX1<4, 2>; // 8
143+
type TDX1<M extends number, N extends number> = Divide<M, N>;
144+
type TDX2 = TDX1<4, 2>; // 2
145+
type TAMX = Add<2, Multiply<5, 8>> // 42
146+
147+
function foo5<T extends number, U extends T>(s: number, x: Add<T, U>, y: Multiply<T, U>) {
148+
s = x;
149+
s = y;
150+
x = s; // Error
151+
x = y; // Error
152+
y = s; // Error
153+
y = x; // Error
154+
}
155+
156+
function foo6<T extends 0 | 1>(x: Add<T, 3>) {
157+
let s: 3 | 4 = x;
158+
}
159+
160+
declare function foo7<T extends number>(x: Integer<T>): T;
161+
162+
function foo8<U extends number>(x: Integer<U>) {
163+
return foo7(x);
164+
}
58165
59166
60167
//// [intrinsicTypes.js]
@@ -73,6 +180,20 @@ function foo2(x) {
73180
function foo4(x) {
74181
return foo3(x);
75182
}
183+
function foo5(s, x, y) {
184+
s = x;
185+
s = y;
186+
x = s; // Error
187+
x = y; // Error
188+
y = s; // Error
189+
y = x; // Error
190+
}
191+
function foo6(x) {
192+
var s = x;
193+
}
194+
function foo8(x) {
195+
return foo7(x);
196+
}
76197
77198
78199
//// [intrinsicTypes.d.ts]
@@ -110,3 +231,89 @@ declare function foo1<T extends string, U extends T>(s: string, x: Uppercase<T>,
110231
declare function foo2<T extends 'foo' | 'bar'>(x: Uppercase<T>): void;
111232
declare function foo3<T extends string>(x: Uppercase<T>): T;
112233
declare function foo4<U extends string>(x: Uppercase<U>): U;
234+
declare type TI1 = Integer<3.5>;
235+
declare type TI2 = Integer<2.5 | 3.4>;
236+
declare type TI3 = Integer<number>;
237+
declare type TI4 = Integer<any>;
238+
declare type TI5 = Integer<never>;
239+
declare type TI6 = Integer<'42'>;
240+
declare type TA1 = Add<4, 2>;
241+
declare type TA2L = Add<4 | 5, 2>;
242+
declare type TA2R = Add<4, 2 | 3>;
243+
declare type TA2LR = Add<4 | 5, 2 | 3>;
244+
declare type TA3L = Add<number, 2>;
245+
declare type TA3R = Add<4, number>;
246+
declare type TA3LR = Add<number, number>;
247+
declare type TA4L = Add<any, 2>;
248+
declare type TA4R = Add<4, any>;
249+
declare type TA4LR = Add<any, any>;
250+
declare type TA5L = Add<never, 2>;
251+
declare type TA5R = Add<4, never>;
252+
declare type TA5LR = Add<never, never>;
253+
declare type TA6L = Add<'4', 2>;
254+
declare type TA6R = Add<4, '2'>;
255+
declare type TA6LR = Add<'4', '2'>;
256+
declare type TS1 = Subtract<4, 2>;
257+
declare type TS2L = Subtract<4 | 5, 2>;
258+
declare type TS2R = Subtract<4, 2 | 3>;
259+
declare type TS2LR = Subtract<4 | 5, 2 | 3>;
260+
declare type TS3L = Subtract<number, 2>;
261+
declare type TS3R = Subtract<4, number>;
262+
declare type TS3LR = Subtract<number, number>;
263+
declare type TS4L = Subtract<any, 2>;
264+
declare type TS4R = Subtract<4, any>;
265+
declare type TS4LR = Subtract<any, any>;
266+
declare type TS5L = Subtract<never, 2>;
267+
declare type TS5R = Subtract<4, never>;
268+
declare type TS5LR = Subtract<never, never>;
269+
declare type TS6L = Subtract<'4', 2>;
270+
declare type TS6R = Subtract<4, '2'>;
271+
declare type TS6LR = Subtract<'4', '2'>;
272+
declare type TM1 = Multiply<4, 2>;
273+
declare type TM2L = Multiply<4 | 5, 2>;
274+
declare type TM2R = Multiply<4, 2 | 3>;
275+
declare type TM2LR = Multiply<4 | 5, 2 | 3>;
276+
declare type TM3L = Multiply<number, 2>;
277+
declare type TM3R = Multiply<4, number>;
278+
declare type TM3LR = Multiply<number, number>;
279+
declare type TM4L = Multiply<any, 2>;
280+
declare type TM4R = Multiply<4, any>;
281+
declare type TM4LR = Multiply<any, any>;
282+
declare type TM5L = Multiply<never, 2>;
283+
declare type TM5R = Multiply<4, never>;
284+
declare type TM5LR = Multiply<never, never>;
285+
declare type TM6L = Multiply<'4', 2>;
286+
declare type TM6R = Multiply<4, '2'>;
287+
declare type TM6LR = Multiply<'4', '2'>;
288+
declare type TD1 = Divide<4, 2>;
289+
declare type TD2L = Divide<4 | 5, 2>;
290+
declare type TD2R = Divide<4, 2 | 4>;
291+
declare type TD2LR = Divide<4 | 5, 2 | 4>;
292+
declare type TD3L = Divide<number, 2>;
293+
declare type TD3R = Divide<4, number>;
294+
declare type TD3LR = Divide<number, number>;
295+
declare type TD4L = Divide<any, 2>;
296+
declare type TD4R = Divide<4, any>;
297+
declare type TD4LR = Divide<any, any>;
298+
declare type TD5L = Divide<never, 2>;
299+
declare type TD5R = Divide<4, never>;
300+
declare type TD5LR = Divide<never, never>;
301+
declare type TD6L = Divide<'4', 2>;
302+
declare type TD6R = Divide<4, '2'>;
303+
declare type TD6LR = Divide<'4', '2'>;
304+
declare type TD7 = Divide<1, 0>;
305+
declare type TIX1<S extends number> = Integer<S>;
306+
declare type TIX2 = TIX1<4.2>;
307+
declare type TAX1<M extends number, N extends number> = Add<M, N>;
308+
declare type TAX2 = TAX1<4, 2>;
309+
declare type TSX1<M extends number, N extends number> = Subtract<M, N>;
310+
declare type TSX2 = TSX1<4, 2>;
311+
declare type TMX1<M extends number, N extends number> = Multiply<M, N>;
312+
declare type TMX2 = TMX1<4, 2>;
313+
declare type TDX1<M extends number, N extends number> = Divide<M, N>;
314+
declare type TDX2 = TDX1<4, 2>;
315+
declare type TAMX = Add<2, Multiply<5, 8>>;
316+
declare function foo5<T extends number, U extends T>(s: number, x: Add<T, U>, y: Multiply<T, U>): void;
317+
declare function foo6<T extends 0 | 1>(x: Add<T, 3>): void;
318+
declare function foo7<T extends number>(x: Integer<T>): T;
319+
declare function foo8<U extends number>(x: Integer<U>): U;

0 commit comments

Comments
 (0)
Failed to load comments.