Skip to content

Commit 0f49703

Browse files
authored
Merge pull request #13427 from Microsoft/nonPrimitiveObjectRelations
Unconstrained type parameter not assignable to 'object' type
2 parents 63333b4 + e90f67d commit 0f49703

File tree

4 files changed

+70
-37
lines changed

4 files changed

+70
-37
lines changed

src/compiler/checker.ts

+17-18
Original file line numberDiff line numberDiff line change
@@ -7172,8 +7172,7 @@ namespace ts {
71727172
if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(<EnumType>source, <EnumType>target, errorReporter)) return true;
71737173
if (source.flags & TypeFlags.Undefined && (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void))) return true;
71747174
if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
7175-
if (source.flags & TypeFlags.Object && target === nonPrimitiveType) return true;
7176-
if (source.flags & TypeFlags.Primitive && target === nonPrimitiveType) return false;
7175+
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.NonPrimitive) return true;
71777176
if (relation === assignableRelation || relation === comparableRelation) {
71787177
if (source.flags & TypeFlags.Any) return true;
71797178
if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true;
@@ -7457,19 +7456,19 @@ namespace ts {
74577456
}
74587457
else {
74597458
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
7460-
7461-
if (!constraint || constraint.flags & TypeFlags.Any) {
7462-
constraint = emptyObjectType;
7463-
}
7464-
7465-
// The constraint may need to be further instantiated with its 'this' type.
7466-
constraint = getTypeWithThisArgument(constraint, source);
7467-
7468-
// Report constraint errors only if the constraint is not the empty object type
7469-
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
7470-
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
7471-
errorInfo = saveErrorInfo;
7472-
return result;
7459+
// A type parameter with no constraint is not related to the non-primitive object type.
7460+
if (constraint || !(target.flags & TypeFlags.NonPrimitive)) {
7461+
if (!constraint || constraint.flags & TypeFlags.Any) {
7462+
constraint = emptyObjectType;
7463+
}
7464+
// The constraint may need to be further instantiated with its 'this' type.
7465+
constraint = getTypeWithThisArgument(constraint, source);
7466+
// Report constraint errors only if the constraint is not the empty object type
7467+
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
7468+
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
7469+
errorInfo = saveErrorInfo;
7470+
return result;
7471+
}
74737472
}
74747473
}
74757474
}
@@ -9237,9 +9236,6 @@ namespace ts {
92379236
}
92389237

92399238
function getTypeFacts(type: Type): TypeFacts {
9240-
if (type === nonPrimitiveType) {
9241-
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
9242-
}
92439239
const flags = type.flags;
92449240
if (flags & TypeFlags.String) {
92459241
return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts;
@@ -9280,6 +9276,9 @@ namespace ts {
92809276
if (flags & TypeFlags.ESSymbol) {
92819277
return strictNullChecks ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts;
92829278
}
9279+
if (flags & TypeFlags.NonPrimitive) {
9280+
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
9281+
}
92839282
if (flags & TypeFlags.TypeParameter) {
92849283
const constraint = getConstraintOfTypeParameter(<TypeParameter>type);
92859284
return getTypeFacts(constraint || emptyObjectType);

tests/baselines/reference/nonPrimitiveInGeneric.errors.txt

+22-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(7,17): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'.
2-
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(8,17): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'.
3-
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(14,7): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'.
4-
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(15,7): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'.
5-
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(21,8): error TS2344: Type 'number' does not satisfy the constraint 'object'.
6-
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(22,8): error TS2344: Type 'string' does not satisfy the constraint 'object'.
7-
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): error TS2344: Type 'number' does not satisfy the constraint 'object'.
1+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(2,9): error TS2322: Type 'T' is not assignable to type 'object'.
2+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(9,17): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'.
3+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(10,17): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'.
4+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(18,7): error TS2345: Argument of type '123' is not assignable to parameter of type 'object'.
5+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(19,7): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'.
6+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(25,8): error TS2344: Type 'number' does not satisfy the constraint 'object'.
7+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,8): error TS2344: Type 'string' does not satisfy the constraint 'object'.
8+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(34,14): error TS2344: Type 'number' does not satisfy the constraint 'object'.
89

910

10-
==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts (7 errors) ====
11-
function generic<T>(t: T) {}
11+
==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts (8 errors) ====
12+
function generic<T>(t: T) {
13+
var o: object = t; // expect error
14+
~
15+
!!! error TS2322: Type 'T' is not assignable to type 'object'.
16+
}
1217
var a = {};
1318
var b = "42";
1419

@@ -21,7 +26,9 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): erro
2126
~
2227
!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'.
2328

24-
function bound<T extends object>(t: T) {}
29+
function bound<T extends object>(t: T) {
30+
var o: object = t; // ok
31+
}
2532

2633
bound({});
2734
bound(a);
@@ -43,6 +50,10 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): erro
4350
~~~~~~
4451
!!! error TS2344: Type 'string' does not satisfy the constraint 'object'.
4552

53+
function bound3<T extends {}>(t: T) {
54+
var o: object = t; // ok
55+
}
56+
4657
interface Proxy<T extends object> {}
4758

4859
var x: Proxy<number>; // error
@@ -53,7 +64,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts(26,14): erro
5364

5465

5566
interface Blah {
56-
foo: number;
67+
foo: number;
5768
}
5869

5970
var u: Proxy<Blah>; // ok

tests/baselines/reference/nonPrimitiveInGeneric.js

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//// [nonPrimitiveInGeneric.ts]
2-
function generic<T>(t: T) {}
2+
function generic<T>(t: T) {
3+
var o: object = t; // expect error
4+
}
35
var a = {};
46
var b = "42";
57

@@ -8,7 +10,9 @@ generic<object>(a);
810
generic<object>(123); // expect error
911
generic<object>(b); // expect error
1012

11-
function bound<T extends object>(t: T) {}
13+
function bound<T extends object>(t: T) {
14+
var o: object = t; // ok
15+
}
1216

1317
bound({});
1418
bound(a);
@@ -22,6 +26,10 @@ bound2<Object>();
2226
bound2<number>(); // expect error
2327
bound2<string>(); // expect error
2428

29+
function bound3<T extends {}>(t: T) {
30+
var o: object = t; // ok
31+
}
32+
2533
interface Proxy<T extends object> {}
2634

2735
var x: Proxy<number>; // error
@@ -30,21 +38,25 @@ var z: Proxy<undefined> ; // ok
3038

3139

3240
interface Blah {
33-
foo: number;
41+
foo: number;
3442
}
3543

3644
var u: Proxy<Blah>; // ok
3745

3846

3947
//// [nonPrimitiveInGeneric.js]
40-
function generic(t) { }
48+
function generic(t) {
49+
var o = t; // expect error
50+
}
4151
var a = {};
4252
var b = "42";
4353
generic({});
4454
generic(a);
4555
generic(123); // expect error
4656
generic(b); // expect error
47-
function bound(t) { }
57+
function bound(t) {
58+
var o = t; // ok
59+
}
4860
bound({});
4961
bound(a);
5062
bound(123); // expect error
@@ -54,6 +66,9 @@ bound2();
5466
bound2();
5567
bound2(); // expect error
5668
bound2(); // expect error
69+
function bound3(t) {
70+
var o = t; // ok
71+
}
5772
var x; // error
5873
var y; // ok
5974
var z; // ok

tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
function generic<T>(t: T) {}
1+
function generic<T>(t: T) {
2+
var o: object = t; // expect error
3+
}
24
var a = {};
35
var b = "42";
46

@@ -7,7 +9,9 @@ generic<object>(a);
79
generic<object>(123); // expect error
810
generic<object>(b); // expect error
911

10-
function bound<T extends object>(t: T) {}
12+
function bound<T extends object>(t: T) {
13+
var o: object = t; // ok
14+
}
1115

1216
bound({});
1317
bound(a);
@@ -21,6 +25,10 @@ bound2<Object>();
2125
bound2<number>(); // expect error
2226
bound2<string>(); // expect error
2327

28+
function bound3<T extends {}>(t: T) {
29+
var o: object = t; // ok
30+
}
31+
2432
interface Proxy<T extends object> {}
2533

2634
var x: Proxy<number>; // error
@@ -29,7 +37,7 @@ var z: Proxy<undefined> ; // ok
2937

3038

3139
interface Blah {
32-
foo: number;
40+
foo: number;
3341
}
3442

3543
var u: Proxy<Blah>; // ok

0 commit comments

Comments
 (0)