Skip to content

Commit

Permalink
Add math intrinsic types
Browse files Browse the repository at this point in the history
  • Loading branch information
skeate committed May 4, 2022
1 parent af027f3 commit 499364f
Show file tree
Hide file tree
Showing 17 changed files with 1,405 additions and 55 deletions.
152 changes: 133 additions & 19 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5160,6 +5160,7 @@ namespace ts {
NonPrimitive = 1 << 26, // intrinsic object type
TemplateLiteral = 1 << 27, // Template literal type
StringMapping = 1 << 28, // Uppercase/Lowercase type
Calculation = 1 << 29, // Math type

/* @internal */
AnyOrUnknown = Any | Unknown,
Expand All @@ -5178,7 +5179,7 @@ namespace ts {
/* @internal */
Primitive = String | Number | BigInt | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal | UniqueESSymbol,
StringLike = String | StringLiteral | TemplateLiteral | StringMapping,
NumberLike = Number | NumberLiteral | Enum,
NumberLike = Number | NumberLiteral | Enum | Calculation,
BigIntLike = BigInt | BigIntLiteral,
BooleanLike = Boolean | BooleanLiteral,
EnumLike = Enum | EnumLiteral,
Expand All @@ -5192,7 +5193,7 @@ namespace ts {
StructuredType = Object | Union | Intersection,
TypeVariable = TypeParameter | IndexedAccess,
InstantiableNonPrimitive = TypeVariable | Conditional | Substitution,
InstantiablePrimitive = Index | TemplateLiteral | StringMapping,
InstantiablePrimitive = Index | TemplateLiteral | StringMapping | Calculation,
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
StructuredOrInstantiable = StructuredType | Instantiable,
/* @internal */
Expand Down Expand Up @@ -5716,6 +5717,11 @@ namespace ts {
type: Type;
}

export interface CalculationType extends InstantiableType {
symbol: Symbol;
types: [Type] | [Type, Type];
}

// Type parameter substitution (TypeFlags.Substitution)
// Substitution types are created for type parameters or indexed access types that occur in the
// true branch of a conditional type. For example, in 'T extends string ? Foo<T> : Bar<T>', the
Expand Down
5 changes: 5 additions & 0 deletions src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,11 @@ namespace FourSlashInterface {
typeEntry("Lowercase"),
typeEntry("Capitalize"),
typeEntry("Uncapitalize"),
typeEntry("Integer"),
typeEntry("Add"),
typeEntry("Subtract"),
typeEntry("Multiply"),
typeEntry("Divide"),
interfaceEntry("ThisType"),
varEntry("ArrayBuffer"),
interfaceEntry("ArrayBufferTypes"),
Expand Down
25 changes: 25 additions & 0 deletions src/lib/es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,31 @@ type Capitalize<S extends string> = intrinsic;
*/
type Uncapitalize<S extends string> = intrinsic;

/**
* Convert number literal type to integer
*/
type Integer<N extends number> = intrinsic;

/**
* Add two literal numbers
*/
type Add<M extends number, N extends number> = intrinsic;

/**
* Subtract two literal numbers
*/
type Subtract<M extends number, N extends number> = intrinsic;

/**
* Multiply two literal numbers
*/
type Multiply<M extends number, N extends number> = intrinsic;

/**
* Divide two literal numbers
*/
type Divide<M extends number, N extends number> = intrinsic;

/**
* Marker for contextual 'this' type
*/
Expand Down
15 changes: 10 additions & 5 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2607,12 +2607,13 @@ declare namespace ts {
NonPrimitive = 67108864,
TemplateLiteral = 134217728,
StringMapping = 268435456,
Calculation = 536870912,
Literal = 2944,
Unit = 109440,
StringOrNumberLiteral = 384,
PossiblyFalsy = 117724,
StringLike = 402653316,
NumberLike = 296,
NumberLike = 536871208,
BigIntLike = 2112,
BooleanLike = 528,
EnumLike = 1056,
Expand All @@ -2622,10 +2623,10 @@ declare namespace ts {
StructuredType = 3670016,
TypeVariable = 8650752,
InstantiableNonPrimitive = 58982400,
InstantiablePrimitive = 406847488,
Instantiable = 465829888,
StructuredOrInstantiable = 469499904,
Narrowable = 536624127,
InstantiablePrimitive = 943718400,
Instantiable = 1002700800,
StructuredOrInstantiable = 1006370816,
Narrowable = 1073495039,
}
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
export interface Type {
Expand Down Expand Up @@ -2787,6 +2788,10 @@ declare namespace ts {
symbol: Symbol;
type: Type;
}
export interface CalculationType extends InstantiableType {
symbol: Symbol;
types: [Type] | [Type, Type];
}
export interface SubstitutionType extends InstantiableType {
objectFlags: ObjectFlags;
baseType: Type;
Expand Down
15 changes: 10 additions & 5 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2607,12 +2607,13 @@ declare namespace ts {
NonPrimitive = 67108864,
TemplateLiteral = 134217728,
StringMapping = 268435456,
Calculation = 536870912,
Literal = 2944,
Unit = 109440,
StringOrNumberLiteral = 384,
PossiblyFalsy = 117724,
StringLike = 402653316,
NumberLike = 296,
NumberLike = 536871208,
BigIntLike = 2112,
BooleanLike = 528,
EnumLike = 1056,
Expand All @@ -2622,10 +2623,10 @@ declare namespace ts {
StructuredType = 3670016,
TypeVariable = 8650752,
InstantiableNonPrimitive = 58982400,
InstantiablePrimitive = 406847488,
Instantiable = 465829888,
StructuredOrInstantiable = 469499904,
Narrowable = 536624127,
InstantiablePrimitive = 943718400,
Instantiable = 1002700800,
StructuredOrInstantiable = 1006370816,
Narrowable = 1073495039,
}
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
export interface Type {
Expand Down Expand Up @@ -2787,6 +2788,10 @@ declare namespace ts {
symbol: Symbol;
type: Type;
}
export interface CalculationType extends InstantiableType {
symbol: Symbol;
types: [Type] | [Type, Type];
}
export interface SubstitutionType extends InstantiableType {
objectFlags: ObjectFlags;
baseType: Type;
Expand Down
163 changes: 162 additions & 1 deletion tests/baselines/reference/intrinsicTypes.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,28 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(42,5): error TS2322:
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322: Type 'Uppercase<T>' is not assignable to type 'Uppercase<U>'.
Type 'T' is not assignable to type 'U'.
'T' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint 'string'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(61,20): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(76,17): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(77,20): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(78,18): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(93,22): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(94,25): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(95,23): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(110,22): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(111,25): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(112,23): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(127,20): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(128,23): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(129,21): error TS2344: Type 'string' does not satisfy the constraint 'number'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(146,5): error TS2322: Type 'number' is not assignable to type 'Add<T, U>'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(147,5): error TS2322: Type 'Multiply<T, U>' is not assignable to type 'Add<T, U>'.
Type 'number' is not assignable to type 'Add<T, U>'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(148,5): error TS2322: Type 'number' is not assignable to type 'Multiply<T, U>'.
tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(149,5): error TS2322: Type 'Add<T, U>' is not assignable to type 'Multiply<T, U>'.
Type 'number' is not assignable to type 'Multiply<T, U>'.


==== tests/cases/conformance/types/typeAliases/intrinsicTypes.ts (8 errors) ====
==== tests/cases/conformance/types/typeAliases/intrinsicTypes.ts (25 errors) ====
type TU1 = Uppercase<'hello'>; // "HELLO"
type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
type TU3 = Uppercase<string>; // string
Expand Down Expand Up @@ -83,4 +102,146 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322:
function foo4<U extends string>(x: Uppercase<U>) {
return foo3(x);
}

type TI1 = Integer<3.5>; // 3
type TI2 = Integer<2.5 | 3.4>; // 2 | 3
type TI3 = Integer<number>; // number
type TI4 = Integer<any>; // any
type TI5 = Integer<never>; // never
type TI6 = Integer<'42'>; // Error
~~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.

type TA1 = Add<4, 2>; // 6
type TA2L = Add<4 | 5, 2>; // 6 | 7
type TA2R = Add<4, 2 | 3>; // 6 | 7
type TA2LR = Add<4 | 5, 2 | 3>; // 6 | 7 | 8
type TA3L = Add<number, 2>; // number
type TA3R = Add<4, number>; // number
type TA3LR = Add<number, number>; // number
type TA4L = Add<any, 2>; // any
type TA4R = Add<4, any>; // any
type TA4LR = Add<any, any>; // any
type TA5L = Add<never, 2>; // never
type TA5R = Add<4, never>; // never
type TA5LR = Add<never, never>; // never
type TA6L = Add<'4', 2>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TA6R = Add<4, '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TA6LR = Add<'4', '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.

type TS1 = Subtract<4, 2>; // 2
type TS2L = Subtract<4 | 5, 2>; // 2 | 3
type TS2R = Subtract<4, 2 | 3>; // 2 | 1
type TS2LR = Subtract<4 | 5, 2 | 3>; // 2 | 1 | 3
type TS3L = Subtract<number, 2>; // number
type TS3R = Subtract<4, number>; // number
type TS3LR = Subtract<number, number>; // number
type TS4L = Subtract<any, 2>; // any
type TS4R = Subtract<4, any>; // any
type TS4LR = Subtract<any, any>; // any
type TS5L = Subtract<never, 2>; // never
type TS5R = Subtract<4, never>; // never
type TS5LR = Subtract<never, never>; // never
type TS6L = Subtract<'4', 2>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TS6R = Subtract<4, '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TS6LR = Subtract<'4', '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.

type TM1 = Multiply<4, 2>; // 8
type TM2L = Multiply<4 | 5, 2>; // 8 | 10
type TM2R = Multiply<4, 2 | 3>; // 8 | 12
type TM2LR = Multiply<4 | 5, 2 | 3>; // 8 | 12 | 10 | 15
type TM3L = Multiply<number, 2>; // number
type TM3R = Multiply<4, number>; // number
type TM3LR = Multiply<number, number>; // number
type TM4L = Multiply<any, 2>; // any
type TM4R = Multiply<4, any>; // any
type TM4LR = Multiply<any, any>; // any
type TM5L = Multiply<never, 2>; // never
type TM5R = Multiply<4, never>; // never
type TM5LR = Multiply<never, never>; // never
type TM6L = Multiply<'4', 2>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TM6R = Multiply<4, '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TM6LR = Multiply<'4', '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.

type TD1 = Divide<4, 2>; // 2
type TD2L = Divide<4 | 5, 2>; // 2 | 2.5
type TD2R = Divide<4, 2 | 4>; // 2 | 1
type TD2LR = Divide<4 | 5, 2 | 4>; // 2 | 1 | 2.5 | 1.25
type TD3L = Divide<number, 2>; // number
type TD3R = Divide<4, number>; // number
type TD3LR = Divide<number, number>; // number
type TD4L = Divide<any, 2>; // any
type TD4R = Divide<4, any>; // any
type TD4LR = Divide<any, any>; // any
type TD5L = Divide<never, 2>; // never
type TD5R = Divide<4, never>; // never
type TD5LR = Divide<never, never>; // never
type TD6L = Divide<'4', 2>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TD6R = Divide<4, '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.
type TD6LR = Divide<'4', '2'>; // Error
~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'number'.

type TIX1<S extends number> = Integer<S>;
type TIX2 = TIX1<4.2>; // 4
type TAX1<M extends number, N extends number> = Add<M, N>;
type TAX2 = TAX1<4, 2>; // 6
type TSX1<M extends number, N extends number> = Subtract<M, N>;
type TSX2 = TSX1<4, 2>; // 6
type TMX1<M extends number, N extends number> = Multiply<M, N>;
type TMX2 = TMX1<4, 2>; // 8
type TDX1<M extends number, N extends number> = Divide<M, N>;
type TDX2 = TDX1<4, 2>; // 2
type TAMX = Add<2, Multiply<5, 8>> // 42

function foo5<T extends number, U extends T>(s: number, x: Add<T, U>, y: Multiply<T, U>) {
s = x;
s = y;
x = s; // Error
~
!!! error TS2322: Type 'number' is not assignable to type 'Add<T, U>'.
x = y; // Error
~
!!! error TS2322: Type 'Multiply<T, U>' is not assignable to type 'Add<T, U>'.
!!! error TS2322: Type 'number' is not assignable to type 'Add<T, U>'.
y = s; // Error
~
!!! error TS2322: Type 'number' is not assignable to type 'Multiply<T, U>'.
y = x; // Error
~
!!! error TS2322: Type 'Add<T, U>' is not assignable to type 'Multiply<T, U>'.
!!! error TS2322: Type 'number' is not assignable to type 'Multiply<T, U>'.
}

function foo6<T extends 0 | 1>(x: Add<T, 3>) {
let s: 3 | 4 = x;
}

declare function foo7<T extends number>(x: Integer<T>): T;

function foo8<U extends number>(x: Integer<U>) {
return foo7(x);
}

Loading

0 comments on commit 499364f

Please sign in to comment.