Skip to content

Commit e9e7fce

Browse files
authored
Merge pull request microsoft#12501 from HerringtonDarkholme/non-primitive
Fix microsoft#1809, introduce non primitive object type
2 parents 91af4ae + 8993877 commit e9e7fce

36 files changed

+978
-7
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3146,6 +3146,7 @@ namespace ts {
31463146
case SyntaxKind.AnyKeyword:
31473147
case SyntaxKind.NumberKeyword:
31483148
case SyntaxKind.NeverKeyword:
3149+
case SyntaxKind.ObjectKeyword:
31493150
case SyntaxKind.StringKeyword:
31503151
case SyntaxKind.BooleanKeyword:
31513152
case SyntaxKind.SymbolKeyword:
@@ -3344,6 +3345,7 @@ namespace ts {
33443345
case SyntaxKind.NumberKeyword:
33453346
case SyntaxKind.NeverKeyword:
33463347
case SyntaxKind.StringKeyword:
3348+
case SyntaxKind.ObjectKeyword:
33473349
case SyntaxKind.BooleanKeyword:
33483350
case SyntaxKind.SymbolKeyword:
33493351
case SyntaxKind.VoidKeyword:

src/compiler/checker.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ namespace ts {
148148
const voidType = createIntrinsicType(TypeFlags.Void, "void");
149149
const neverType = createIntrinsicType(TypeFlags.Never, "never");
150150
const silentNeverType = createIntrinsicType(TypeFlags.Never, "never");
151+
const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object");
151152

152153
const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
153154

@@ -4196,6 +4197,7 @@ namespace ts {
41964197
case SyntaxKind.NumberKeyword:
41974198
case SyntaxKind.BooleanKeyword:
41984199
case SyntaxKind.SymbolKeyword:
4200+
case SyntaxKind.ObjectKeyword:
41994201
case SyntaxKind.VoidKeyword:
42004202
case SyntaxKind.UndefinedKeyword:
42014203
case SyntaxKind.NullKeyword:
@@ -4780,6 +4782,7 @@ namespace ts {
47804782
t.flags & TypeFlags.NumberLike ? globalNumberType :
47814783
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
47824784
t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() :
4785+
t.flags & TypeFlags.NonPrimitive ? globalObjectType :
47834786
t;
47844787
}
47854788

@@ -6405,6 +6408,8 @@ namespace ts {
64056408
return nullType;
64066409
case SyntaxKind.NeverKeyword:
64076410
return neverType;
6411+
case SyntaxKind.ObjectKeyword:
6412+
return nonPrimitiveType;
64086413
case SyntaxKind.JSDocNullKeyword:
64096414
return nullType;
64106415
case SyntaxKind.JSDocUndefinedKeyword:
@@ -7162,6 +7167,8 @@ namespace ts {
71627167
if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(<EnumType>source, <EnumType>target, errorReporter)) return true;
71637168
if (source.flags & TypeFlags.Undefined && (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void))) return true;
71647169
if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
7170+
if (source.flags & TypeFlags.Object && target === nonPrimitiveType) return true;
7171+
if (source.flags & TypeFlags.Primitive && target === nonPrimitiveType) return false;
71657172
if (relation === assignableRelation || relation === comparableRelation) {
71667173
if (source.flags & TypeFlags.Any) return true;
71677174
if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true;
@@ -9235,6 +9242,9 @@ namespace ts {
92359242
}
92369243

92379244
function getTypeFacts(type: Type): TypeFacts {
9245+
if (type === nonPrimitiveType) {
9246+
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
9247+
}
92389248
const flags = type.flags;
92399249
if (flags & TypeFlags.String) {
92409250
return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts;
@@ -18159,6 +18169,7 @@ namespace ts {
1815918169
case "string":
1816018170
case "symbol":
1816118171
case "void":
18172+
case "object":
1816218173
error(name, message, (<Identifier>name).text);
1816318174
}
1816418175
}

src/compiler/parser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,6 +2510,7 @@ namespace ts {
25102510
case SyntaxKind.SymbolKeyword:
25112511
case SyntaxKind.UndefinedKeyword:
25122512
case SyntaxKind.NeverKeyword:
2513+
case SyntaxKind.ObjectKeyword:
25132514
// If these are followed by a dot, then parse these out as a dotted type reference instead.
25142515
const node = tryParse(parseKeywordAndNoDot);
25152516
return node || parseTypeReference();
@@ -2568,6 +2569,7 @@ namespace ts {
25682569
case SyntaxKind.NumericLiteral:
25692570
case SyntaxKind.TrueKeyword:
25702571
case SyntaxKind.FalseKeyword:
2572+
case SyntaxKind.ObjectKeyword:
25712573
return true;
25722574
case SyntaxKind.MinusToken:
25732575
return lookAhead(nextTokenIsNumericLiteral);
@@ -6037,6 +6039,7 @@ namespace ts {
60376039
case SyntaxKind.NullKeyword:
60386040
case SyntaxKind.UndefinedKeyword:
60396041
case SyntaxKind.NeverKeyword:
6042+
case SyntaxKind.ObjectKeyword:
60406043
return parseTokenNode<JSDocType>();
60416044
case SyntaxKind.StringLiteral:
60426045
case SyntaxKind.NumericLiteral:

src/compiler/scanner.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ namespace ts {
9898
"new": SyntaxKind.NewKeyword,
9999
"null": SyntaxKind.NullKeyword,
100100
"number": SyntaxKind.NumberKeyword,
101+
"object": SyntaxKind.ObjectKeyword,
101102
"package": SyntaxKind.PackageKeyword,
102103
"private": SyntaxKind.PrivateKeyword,
103104
"protected": SyntaxKind.ProtectedKeyword,

src/compiler/types.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ namespace ts {
175175
ReadonlyKeyword,
176176
RequireKeyword,
177177
NumberKeyword,
178+
ObjectKeyword,
178179
SetKeyword,
179180
StringKeyword,
180181
SymbolKeyword,
@@ -816,6 +817,7 @@ namespace ts {
816817
export interface KeywordTypeNode extends TypeNode {
817818
kind: SyntaxKind.AnyKeyword
818819
| SyntaxKind.NumberKeyword
820+
| SyntaxKind.ObjectKeyword
819821
| SyntaxKind.BooleanKeyword
820822
| SyntaxKind.StringKeyword
821823
| SyntaxKind.SymbolKeyword
@@ -2785,6 +2787,7 @@ namespace ts {
27852787
ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type
27862788
/* @internal */
27872789
ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type
2790+
NonPrimitive = 1 << 24, // intrinsic object type
27882791

27892792
/* @internal */
27902793
Nullable = Undefined | Null,
@@ -2794,7 +2797,7 @@ namespace ts {
27942797
DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null,
27952798
PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean,
27962799
/* @internal */
2797-
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never,
2800+
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
27982801
/* @internal */
27992802
Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal,
28002803
StringLike = String | StringLiteral | Index,
@@ -2808,8 +2811,8 @@ namespace ts {
28082811

28092812
// 'Narrowable' types are types where narrowing actually narrows.
28102813
// This *should* be every type other than null, undefined, void, and never
2811-
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol,
2812-
NotUnionOrUnit = Any | ESSymbol | Object,
2814+
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive,
2815+
NotUnionOrUnit = Any | ESSymbol | Object | NonPrimitive,
28132816
/* @internal */
28142817
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
28152818
/* @internal */
@@ -2863,6 +2866,7 @@ namespace ts {
28632866
ObjectLiteral = 1 << 7, // Originates in an object literal
28642867
EvolvingArray = 1 << 8, // Evolving array type
28652868
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
2869+
NonPrimitive = 1 << 10, // NonPrimitive object type
28662870
ClassOrInterface = Class | Interface
28672871
}
28682872

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//// [assignObjectToNonPrimitive.ts]
2+
var x = {};
3+
var y = {foo: "bar"};
4+
var a: object;
5+
a = x;
6+
a = y;
7+
8+
9+
//// [assignObjectToNonPrimitive.js]
10+
var x = {};
11+
var y = { foo: "bar" };
12+
var a;
13+
a = x;
14+
a = y;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/conformance/types/nonPrimitive/assignObjectToNonPrimitive.ts ===
2+
var x = {};
3+
>x : Symbol(x, Decl(assignObjectToNonPrimitive.ts, 0, 3))
4+
5+
var y = {foo: "bar"};
6+
>y : Symbol(y, Decl(assignObjectToNonPrimitive.ts, 1, 3))
7+
>foo : Symbol(foo, Decl(assignObjectToNonPrimitive.ts, 1, 9))
8+
9+
var a: object;
10+
>a : Symbol(a, Decl(assignObjectToNonPrimitive.ts, 2, 3))
11+
12+
a = x;
13+
>a : Symbol(a, Decl(assignObjectToNonPrimitive.ts, 2, 3))
14+
>x : Symbol(x, Decl(assignObjectToNonPrimitive.ts, 0, 3))
15+
16+
a = y;
17+
>a : Symbol(a, Decl(assignObjectToNonPrimitive.ts, 2, 3))
18+
>y : Symbol(y, Decl(assignObjectToNonPrimitive.ts, 1, 3))
19+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== tests/cases/conformance/types/nonPrimitive/assignObjectToNonPrimitive.ts ===
2+
var x = {};
3+
>x : {}
4+
>{} : {}
5+
6+
var y = {foo: "bar"};
7+
>y : { foo: string; }
8+
>{foo: "bar"} : { foo: string; }
9+
>foo : string
10+
>"bar" : "bar"
11+
12+
var a: object;
13+
>a : object
14+
15+
a = x;
16+
>a = x : {}
17+
>a : object
18+
>x : {}
19+
20+
a = y;
21+
>a = y : { foo: string; }
22+
>a : object
23+
>y : { foo: string; }
24+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts(3,3): error TS2339: Property 'nonExist' does not exist on type 'object'.
2+
3+
4+
==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts (1 errors) ====
5+
var a: object;
6+
a.toString();
7+
a.nonExist(); // error
8+
~~~~~~~~
9+
!!! error TS2339: Property 'nonExist' does not exist on type 'object'.
10+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [nonPrimitiveAccessProperty.ts]
2+
var a: object;
3+
a.toString();
4+
a.nonExist(); // error
5+
6+
7+
//// [nonPrimitiveAccessProperty.js]
8+
var a;
9+
a.toString();
10+
a.nonExist(); // error

0 commit comments

Comments
 (0)