diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 34ee591a64f42..d97e232ec31c2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -144,9 +144,9 @@ namespace ts { const voidType = createIntrinsicType(TypeFlags.Void, "void"); const neverType = createIntrinsicType(TypeFlags.Never, "never"); const silentNeverType = createIntrinsicType(TypeFlags.Never, "never"); + const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const nonPrimitiveType = createNonPrimitiveType(); const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral | SymbolFlags.Transient, "__type"); emptyTypeLiteralSymbol.members = createMap(); @@ -1662,13 +1662,6 @@ namespace ts { return type; } - function createNonPrimitiveType(): ResolvedType { - const type = setStructuredTypeMembers( - createObjectType(ObjectFlags.NonPrimitive, undefined), - emptySymbols, emptyArray, emptyArray, undefined, undefined); - return type; - } - function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType { const type = createType(TypeFlags.Object); type.objectFlags = objectFlags; @@ -2297,9 +2290,6 @@ namespace ts { else if (type.flags & TypeFlags.UnionOrIntersection) { writeUnionOrIntersectionType(type, nextFlags); } - else if (getObjectFlags(type) & ObjectFlags.NonPrimitive) { - writer.writeKeyword("object"); - } else if (getObjectFlags(type) & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) { writeAnonymousType(type, nextFlags); } @@ -4748,6 +4738,7 @@ namespace ts { t.flags & TypeFlags.NumberLike ? globalNumberType : t.flags & TypeFlags.BooleanLike ? globalBooleanType : t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() : + t.flags & TypeFlags.NonPrimitive ? globalObjectType : t; } @@ -7122,6 +7113,8 @@ namespace ts { if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(source, target, errorReporter)) return true; if (source.flags & TypeFlags.Undefined && (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void))) return true; if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true; + if (source.flags & TypeFlags.Object && target === nonPrimitiveType) return true; + if (source.flags & TypeFlags.Primitive && target === nonPrimitiveType) return false; if (relation === assignableRelation || relation === comparableRelation) { if (source.flags & TypeFlags.Any) return true; if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true; @@ -7440,7 +7433,7 @@ namespace ts { } } } - else if (!(source.flags & TypeFlags.Primitive && target === nonPrimitiveType)) { + else { if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { // We have type references to same target type, see if relationship holds for all type arguments if (result = typeArgumentsRelatedTo(source, target, reportErrors)) { @@ -9190,6 +9183,9 @@ namespace ts { } function getTypeFacts(type: Type): TypeFacts { + if (type === nonPrimitiveType) { + return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; + } const flags = type.flags; if (flags & TypeFlags.String) { return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index db919b56449ec..5b411ffea300f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2781,6 +2781,7 @@ namespace ts { ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type /* @internal */ ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type + NonPrimitive = 1 << 24, // intrinsic object type /* @internal */ Nullable = Undefined | Null, @@ -2790,7 +2791,7 @@ namespace ts { DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null, PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean, /* @internal */ - Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never, + Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive, /* @internal */ Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal, StringLike = String | StringLiteral | Index, @@ -2798,14 +2799,14 @@ namespace ts { BooleanLike = Boolean | BooleanLiteral, EnumLike = Enum | EnumLiteral, UnionOrIntersection = Union | Intersection, - StructuredType = Object | Union | Intersection, + StructuredType = Object | Union | Intersection | NonPrimitive, StructuredOrTypeParameter = StructuredType | TypeParameter | Index, TypeVariable = TypeParameter | IndexedAccess, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol, - NotUnionOrUnit = Any | ESSymbol | Object, + NotUnionOrUnit = Any | ESSymbol | Object | NonPrimitive, /* @internal */ RequiresWidening = ContainsWideningType | ContainsObjectLiteral, /* @internal */ diff --git a/tests/baselines/reference/nonPrimitiveAssignError.errors.txt b/tests/baselines/reference/nonPrimitiveAssignError.errors.txt index bb62d494d749a..a9bfaaa4a8a4c 100644 --- a/tests/baselines/reference/nonPrimitiveAssignError.errors.txt +++ b/tests/baselines/reference/nonPrimitiveAssignError.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(5,1): error TS2322: Type 'object' is not assignable to type '{ foo: string; }'. - Property 'foo' is missing in type 'object'. + Property 'foo' is missing in type 'Object'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(13,1): error TS2322: Type 'number' is not assignable to type 'object'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(14,1): error TS2322: Type 'true' is not assignable to type 'object'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(15,1): error TS2322: Type 'string' is not assignable to type 'object'. @@ -16,7 +16,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(19,1): err y = a; // expect error ~ !!! error TS2322: Type 'object' is not assignable to type '{ foo: string; }'. -!!! error TS2322: Property 'foo' is missing in type 'object'. +!!! error TS2322: Property 'foo' is missing in type 'Object'. a = x; a = y;