Skip to content

Commit 3bfbe68

Browse files
authored
Merge pull request microsoft#23806 from Microsoft/objectAndUnconstrainedTypeParameter
Unconstrained type variable not assignable to 'object'
2 parents 9f4abe2 + 0066b02 commit 3bfbe68

File tree

6 files changed

+178
-9
lines changed

6 files changed

+178
-9
lines changed

src/compiler/checker.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -10716,19 +10716,18 @@ namespace ts {
1071610716
return result;
1071710717
}
1071810718
}
10719-
let constraint = getConstraintForRelation(<TypeParameter>source);
10720-
// A type variable with no constraint is not related to the non-primitive object type.
10721-
if (constraint || !(target.flags & TypeFlags.NonPrimitive)) {
10722-
if (!constraint || constraint.flags & TypeFlags.Any) {
10723-
constraint = emptyObjectType;
10724-
}
10725-
// Report constraint errors only if the constraint is not the empty object type
10726-
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
10727-
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
10719+
const constraint = getConstraintForRelation(<TypeParameter>source);
10720+
if (!constraint || constraint.flags & TypeFlags.Any) {
10721+
// A type variable with no constraint is not related to the non-primitive object type.
10722+
if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) {
1072810723
errorInfo = saveErrorInfo;
1072910724
return result;
1073010725
}
1073110726
}
10727+
else if (result = isRelatedTo(constraint, target, reportErrors)) {
10728+
errorInfo = saveErrorInfo;
10729+
return result;
10730+
}
1073210731
}
1073310732
else if (source.flags & TypeFlags.Index) {
1073410733
if (result = isRelatedTo(keyofConstraintType, target, reportErrors)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAndTypeVariables.ts(10,9): error TS2322: Type 'T' is not assignable to type 'object'.
2+
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAndTypeVariables.ts(11,9): error TS2322: Type 'T' is not assignable to type 'object | U'.
3+
Type 'T' is not assignable to type 'U'.
4+
5+
6+
==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveAndTypeVariables.ts (2 errors) ====
7+
// Repros from #23800
8+
9+
type A<T, V> = { [P in keyof T]: T[P] extends V ? 1 : 0; };
10+
type B<T, V> = { [P in keyof T]: T[P] extends V | object ? 1 : 0; };
11+
12+
let a: A<{ a: 0 | 1 }, 0> = { a: 0 };
13+
let b: B<{ a: 0 | 1 }, 0> = { a: 0 };
14+
15+
function foo<T, U>(x: T) {
16+
let a: object = x; // Error
17+
~
18+
!!! error TS2322: Type 'T' is not assignable to type 'object'.
19+
let b: U | object = x; // Error
20+
~
21+
!!! error TS2322: Type 'T' is not assignable to type 'object | U'.
22+
!!! error TS2322: Type 'T' is not assignable to type 'U'.
23+
}
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [nonPrimitiveAndTypeVariables.ts]
2+
// Repros from #23800
3+
4+
type A<T, V> = { [P in keyof T]: T[P] extends V ? 1 : 0; };
5+
type B<T, V> = { [P in keyof T]: T[P] extends V | object ? 1 : 0; };
6+
7+
let a: A<{ a: 0 | 1 }, 0> = { a: 0 };
8+
let b: B<{ a: 0 | 1 }, 0> = { a: 0 };
9+
10+
function foo<T, U>(x: T) {
11+
let a: object = x; // Error
12+
let b: U | object = x; // Error
13+
}
14+
15+
16+
//// [nonPrimitiveAndTypeVariables.js]
17+
"use strict";
18+
// Repros from #23800
19+
var a = { a: 0 };
20+
var b = { a: 0 };
21+
function foo(x) {
22+
var a = x; // Error
23+
var b = x; // Error
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
=== tests/cases/conformance/types/nonPrimitive/nonPrimitiveAndTypeVariables.ts ===
2+
// Repros from #23800
3+
4+
type A<T, V> = { [P in keyof T]: T[P] extends V ? 1 : 0; };
5+
>A : Symbol(A, Decl(nonPrimitiveAndTypeVariables.ts, 0, 0))
6+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 2, 7))
7+
>V : Symbol(V, Decl(nonPrimitiveAndTypeVariables.ts, 2, 9))
8+
>P : Symbol(P, Decl(nonPrimitiveAndTypeVariables.ts, 2, 18))
9+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 2, 7))
10+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 2, 7))
11+
>P : Symbol(P, Decl(nonPrimitiveAndTypeVariables.ts, 2, 18))
12+
>V : Symbol(V, Decl(nonPrimitiveAndTypeVariables.ts, 2, 9))
13+
14+
type B<T, V> = { [P in keyof T]: T[P] extends V | object ? 1 : 0; };
15+
>B : Symbol(B, Decl(nonPrimitiveAndTypeVariables.ts, 2, 59))
16+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 3, 7))
17+
>V : Symbol(V, Decl(nonPrimitiveAndTypeVariables.ts, 3, 9))
18+
>P : Symbol(P, Decl(nonPrimitiveAndTypeVariables.ts, 3, 18))
19+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 3, 7))
20+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 3, 7))
21+
>P : Symbol(P, Decl(nonPrimitiveAndTypeVariables.ts, 3, 18))
22+
>V : Symbol(V, Decl(nonPrimitiveAndTypeVariables.ts, 3, 9))
23+
24+
let a: A<{ a: 0 | 1 }, 0> = { a: 0 };
25+
>a : Symbol(a, Decl(nonPrimitiveAndTypeVariables.ts, 5, 3))
26+
>A : Symbol(A, Decl(nonPrimitiveAndTypeVariables.ts, 0, 0))
27+
>a : Symbol(a, Decl(nonPrimitiveAndTypeVariables.ts, 5, 10))
28+
>a : Symbol(a, Decl(nonPrimitiveAndTypeVariables.ts, 5, 29))
29+
30+
let b: B<{ a: 0 | 1 }, 0> = { a: 0 };
31+
>b : Symbol(b, Decl(nonPrimitiveAndTypeVariables.ts, 6, 3))
32+
>B : Symbol(B, Decl(nonPrimitiveAndTypeVariables.ts, 2, 59))
33+
>a : Symbol(a, Decl(nonPrimitiveAndTypeVariables.ts, 6, 10))
34+
>a : Symbol(a, Decl(nonPrimitiveAndTypeVariables.ts, 6, 29))
35+
36+
function foo<T, U>(x: T) {
37+
>foo : Symbol(foo, Decl(nonPrimitiveAndTypeVariables.ts, 6, 37))
38+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 8, 13))
39+
>U : Symbol(U, Decl(nonPrimitiveAndTypeVariables.ts, 8, 15))
40+
>x : Symbol(x, Decl(nonPrimitiveAndTypeVariables.ts, 8, 19))
41+
>T : Symbol(T, Decl(nonPrimitiveAndTypeVariables.ts, 8, 13))
42+
43+
let a: object = x; // Error
44+
>a : Symbol(a, Decl(nonPrimitiveAndTypeVariables.ts, 9, 7))
45+
>x : Symbol(x, Decl(nonPrimitiveAndTypeVariables.ts, 8, 19))
46+
47+
let b: U | object = x; // Error
48+
>b : Symbol(b, Decl(nonPrimitiveAndTypeVariables.ts, 10, 7))
49+
>U : Symbol(U, Decl(nonPrimitiveAndTypeVariables.ts, 8, 15))
50+
>x : Symbol(x, Decl(nonPrimitiveAndTypeVariables.ts, 8, 19))
51+
}
52+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
=== tests/cases/conformance/types/nonPrimitive/nonPrimitiveAndTypeVariables.ts ===
2+
// Repros from #23800
3+
4+
type A<T, V> = { [P in keyof T]: T[P] extends V ? 1 : 0; };
5+
>A : A<T, V>
6+
>T : T
7+
>V : V
8+
>P : P
9+
>T : T
10+
>T : T
11+
>P : P
12+
>V : V
13+
14+
type B<T, V> = { [P in keyof T]: T[P] extends V | object ? 1 : 0; };
15+
>B : B<T, V>
16+
>T : T
17+
>V : V
18+
>P : P
19+
>T : T
20+
>T : T
21+
>P : P
22+
>V : V
23+
24+
let a: A<{ a: 0 | 1 }, 0> = { a: 0 };
25+
>a : A<{ a: 0 | 1; }, 0>
26+
>A : A<T, V>
27+
>a : 0 | 1
28+
>{ a: 0 } : { a: 0; }
29+
>a : 0
30+
>0 : 0
31+
32+
let b: B<{ a: 0 | 1 }, 0> = { a: 0 };
33+
>b : B<{ a: 0 | 1; }, 0>
34+
>B : B<T, V>
35+
>a : 0 | 1
36+
>{ a: 0 } : { a: 0; }
37+
>a : 0
38+
>0 : 0
39+
40+
function foo<T, U>(x: T) {
41+
>foo : <T, U>(x: T) => void
42+
>T : T
43+
>U : U
44+
>x : T
45+
>T : T
46+
47+
let a: object = x; // Error
48+
>a : object
49+
>x : T
50+
51+
let b: U | object = x; // Error
52+
>b : object | U
53+
>U : U
54+
>x : T
55+
}
56+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// @strict: true
2+
3+
// Repros from #23800
4+
5+
type A<T, V> = { [P in keyof T]: T[P] extends V ? 1 : 0; };
6+
type B<T, V> = { [P in keyof T]: T[P] extends V | object ? 1 : 0; };
7+
8+
let a: A<{ a: 0 | 1 }, 0> = { a: 0 };
9+
let b: B<{ a: 0 | 1 }, 0> = { a: 0 };
10+
11+
function foo<T, U>(x: T) {
12+
let a: object = x; // Error
13+
let b: U | object = x; // Error
14+
}

0 commit comments

Comments
 (0)