Merge pull request #13427 from Microsoft/nonPrimitiveObjectRelations

Unconstrained type parameter not assignable to 'object' type
This commit is contained in:
Anders Hejlsberg 2017-01-12 13:19:27 -10:00 committed by GitHub
commit 0f49703030
4 changed files with 70 additions and 37 deletions

View file

@ -7172,8 +7172,7 @@ namespace ts {
if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(<EnumType>source, <EnumType>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(<TypeParameter>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(<TypeParameter>type);
return getTypeFacts(constraint || emptyObjectType);

View file

@ -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: T) {}
==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts (8 errors) ====
function generic<T>(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 extends object>(t: T) {}
function bound<T extends object>(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 extends {}>(t: T) {
var o: object = t; // ok
}
interface Proxy<T extends object> {}
var x: Proxy<number>; // error
@ -53,7 +64,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): erro
interface Blah {
foo: number;
foo: number;
}
var u: Proxy<Blah>; // ok

View file

@ -1,5 +1,7 @@
//// [nonPrimitiveInGeneric.ts]
function generic<T>(t: T) {}
function generic<T>(t: T) {
var o: object = t; // expect error
}
var a = {};
var b = "42";
@ -8,7 +10,9 @@ generic<object>(a);
generic<object>(123); // expect error
generic<object>(b); // expect error
function bound<T extends object>(t: T) {}
function bound<T extends object>(t: T) {
var o: object = t; // ok
}
bound({});
bound(a);
@ -22,6 +26,10 @@ bound2<Object>();
bound2<number>(); // expect error
bound2<string>(); // expect error
function bound3<T extends {}>(t: T) {
var o: object = t; // ok
}
interface Proxy<T extends object> {}
var x: Proxy<number>; // error
@ -30,21 +38,25 @@ var z: Proxy<undefined> ; // ok
interface Blah {
foo: number;
foo: number;
}
var u: Proxy<Blah>; // 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

View file

@ -1,4 +1,6 @@
function generic<T>(t: T) {}
function generic<T>(t: T) {
var o: object = t; // expect error
}
var a = {};
var b = "42";
@ -7,7 +9,9 @@ generic<object>(a);
generic<object>(123); // expect error
generic<object>(b); // expect error
function bound<T extends object>(t: T) {}
function bound<T extends object>(t: T) {
var o: object = t; // ok
}
bound({});
bound(a);
@ -21,6 +25,10 @@ bound2<Object>();
bound2<number>(); // expect error
bound2<string>(); // expect error
function bound3<T extends {}>(t: T) {
var o: object = t; // ok
}
interface Proxy<T extends object> {}
var x: Proxy<number>; // error
@ -29,7 +37,7 @@ var z: Proxy<undefined> ; // ok
interface Blah {
foo: number;
foo: number;
}
var u: Proxy<Blah>; // ok