diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cc4afc8aa3eca..e92ea973f8f18 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7172,8 +7172,7 @@ 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 (source.flags & TypeFlags.Object && target.flags & TypeFlags.NonPrimitive) return true; 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; @@ -7457,19 +7456,19 @@ namespace ts { } else { let constraint = getConstraintOfTypeParameter(source); - - if (!constraint || constraint.flags & TypeFlags.Any) { - constraint = emptyObjectType; - } - - // The constraint may need to be further instantiated with its 'this' type. - constraint = getTypeWithThisArgument(constraint, source); - - // Report constraint errors only if the constraint is not the empty object type - const reportConstraintErrors = reportErrors && constraint !== emptyObjectType; - if (result = isRelatedTo(constraint, target, reportConstraintErrors)) { - errorInfo = saveErrorInfo; - return result; + // A type parameter with no constraint is not related to the non-primitive object type. + if (constraint || !(target.flags & TypeFlags.NonPrimitive)) { + if (!constraint || constraint.flags & TypeFlags.Any) { + constraint = emptyObjectType; + } + // The constraint may need to be further instantiated with its 'this' type. + constraint = getTypeWithThisArgument(constraint, source); + // Report constraint errors only if the constraint is not the empty object type + const reportConstraintErrors = reportErrors && constraint !== emptyObjectType; + if (result = isRelatedTo(constraint, target, reportConstraintErrors)) { + errorInfo = saveErrorInfo; + return result; + } } } } @@ -9237,9 +9236,6 @@ 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; @@ -9280,6 +9276,9 @@ namespace ts { if (flags & TypeFlags.ESSymbol) { return strictNullChecks ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts; } + if (flags & TypeFlags.NonPrimitive) { + return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; + } if (flags & TypeFlags.TypeParameter) { const constraint = getConstraintOfTypeParameter(type); return getTypeFacts(constraint || emptyObjectType); diff --git a/tests/baselines/reference/nonPrimitiveInGeneric.errors.txt b/tests/baselines/reference/nonPrimitiveInGeneric.errors.txt index 04d4ee4a1a795..ce257c876809d 100644 --- a/tests/baselines/reference/nonPrimitiveInGeneric.errors.txt +++ b/tests/baselines/reference/nonPrimitiveInGeneric.errors.txt @@ -1,14 +1,19 @@ -tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(7,17): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'. -tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(8,17): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'. -tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(14,7): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'. -tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(15,7): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'. -tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(21,8): error TS2344: Type 'number' does not satisfy the constraint 'object'. -tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(22,8): error TS2344: Type 'string' does not satisfy the constraint 'object'. -tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): error TS2344: Type 'number' does not satisfy the constraint 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(2,9): error TS2322: Type 'T' is not assignable to type 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(9,17): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(10,17): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(18,7): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(19,7): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(25,8): error TS2344: Type 'number' does not satisfy the constraint 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,8): error TS2344: Type 'string' does not satisfy the constraint 'object'. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(34,14): error TS2344: Type 'number' does not satisfy the constraint 'object'. -==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts (7 errors) ==== - function generic(t: T) {} +==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts (8 errors) ==== + function generic(t: T) { + var o: object = t; // expect error + ~ +!!! error TS2322: Type 'T' is not assignable to type 'object'. + } var a = {}; var b = "42"; @@ -21,7 +26,9 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): erro ~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'. - function bound(t: T) {} + function bound(t: T) { + var o: object = t; // ok + } bound({}); bound(a); @@ -43,6 +50,10 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): erro ~~~~~~ !!! error TS2344: Type 'string' does not satisfy the constraint 'object'. + function bound3(t: T) { + var o: object = t; // ok + } + interface Proxy {} var x: Proxy; // error @@ -53,7 +64,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): erro interface Blah { - foo: number; + foo: number; } var u: Proxy; // ok diff --git a/tests/baselines/reference/nonPrimitiveInGeneric.js b/tests/baselines/reference/nonPrimitiveInGeneric.js index b7080e149b413..2db357c3eb594 100644 --- a/tests/baselines/reference/nonPrimitiveInGeneric.js +++ b/tests/baselines/reference/nonPrimitiveInGeneric.js @@ -1,5 +1,7 @@ //// [nonPrimitiveInGeneric.ts] -function generic(t: T) {} +function generic(t: T) { + var o: object = t; // expect error +} var a = {}; var b = "42"; @@ -8,7 +10,9 @@ generic(a); generic(123); // expect error generic(b); // expect error -function bound(t: T) {} +function bound(t: T) { + var o: object = t; // ok +} bound({}); bound(a); @@ -22,6 +26,10 @@ bound2(); bound2(); // expect error bound2(); // expect error +function bound3(t: T) { + var o: object = t; // ok +} + interface Proxy {} var x: Proxy; // error @@ -30,21 +38,25 @@ var z: Proxy ; // ok interface Blah { - foo: number; + foo: number; } var u: Proxy; // ok //// [nonPrimitiveInGeneric.js] -function generic(t) { } +function generic(t) { + var o = t; // expect error +} var a = {}; var b = "42"; generic({}); generic(a); generic(123); // expect error generic(b); // expect error -function bound(t) { } +function bound(t) { + var o = t; // ok +} bound({}); bound(a); bound(123); // expect error @@ -54,6 +66,9 @@ bound2(); bound2(); bound2(); // expect error bound2(); // expect error +function bound3(t) { + var o = t; // ok +} var x; // error var y; // ok var z; // ok diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts index a19271a59d3ea..836896b5a57fc 100644 --- a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts @@ -1,4 +1,6 @@ -function generic(t: T) {} +function generic(t: T) { + var o: object = t; // expect error +} var a = {}; var b = "42"; @@ -7,7 +9,9 @@ generic(a); generic(123); // expect error generic(b); // expect error -function bound(t: T) {} +function bound(t: T) { + var o: object = t; // ok +} bound({}); bound(a); @@ -21,6 +25,10 @@ bound2(); bound2(); // expect error bound2(); // expect error +function bound3(t: T) { + var o: object = t; // ok +} + interface Proxy {} var x: Proxy; // error @@ -29,7 +37,7 @@ var z: Proxy ; // ok interface Blah { - foo: number; + foo: number; } var u: Proxy; // ok