Skip to content

Commit

Permalink
Make the unconstrained type parameter and {} assignability rule not a…
Browse files Browse the repository at this point in the history
…pply under strictNullChecks (microsoft#48366)

* Make the unconstrained type parameter and {} assignability rule not apply under strictNullChecks

* Fix lint, PR feedback
# Conflicts:
#	src/compiler/checker.ts
#	tests/baselines/reference/unknownType1.errors.txt
  • Loading branch information
RyanCavanaugh committed May 26, 2022
1 parent 954e80a commit a16b1ad
Show file tree
Hide file tree
Showing 10 changed files with 824 additions and 13 deletions.
10 changes: 3 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18812,6 +18812,9 @@ namespace ts {
return;
}
reportRelationError(headMessage, source, target);
if (strictNullChecks && source.flags & TypeFlags.TypeVariable && source.symbol?.declarations?.[0] && !getConstraintOfType(source as TypeVariable) && isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) {
associateRelatedInfo(createDiagnosticForNode(source.symbol.declarations[0], Diagnostics.This_type_parameter_probably_needs_an_extends_object_constraint));
}
}

function traceUnionsOrIntersectionsTooLarge(source: Type, target: Type): void {
Expand Down Expand Up @@ -19616,13 +19619,6 @@ namespace ts {
// IndexedAccess comparisons are handled above in the `targetFlags & TypeFlage.IndexedAccess` branch
if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) {
const constraint = getConstraintOfType(source as TypeVariable) || unknownType;
if (!getConstraintOfType(source as TypeVariable) || (sourceFlags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) {
// A type variable with no constraint is not related to the non-primitive object type.
if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive), RecursionFlags.Both)) {
resetErrorInfo(saveErrorInfo);
return result;
}
}
// hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed
if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) {
resetErrorInfo(saveErrorInfo);
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,10 @@
"category": "Error",
"code": 2207
},
"This type parameter probably needs an `extends object` constraint.": {
"category": "Error",
"code": 2208
},

"The project root is ambiguous, but is required to resolve export map entry '{0}' in file '{1}'. Supply the `rootDir` compiler option to disambiguate.": {
"category": "Error",
Expand Down
8 changes: 7 additions & 1 deletion tests/baselines/reference/conditionalTypes1.errors.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
tests/cases/conformance/types/conditional/conditionalTypes1.ts(12,5): error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
Type 'T' is not assignable to type '{}'.
tests/cases/conformance/types/conditional/conditionalTypes1.ts(17,5): error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
Type 'string | undefined' is not assignable to type 'NonNullable<T>'.
Type 'undefined' is not assignable to type 'NonNullable<T>'.
Expand Down Expand Up @@ -66,7 +68,7 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
Type 'boolean' is not assignable to type 'true'.


==== tests/cases/conformance/types/conditional/conditionalTypes1.ts (19 errors) ====
==== tests/cases/conformance/types/conditional/conditionalTypes1.ts (20 errors) ====
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"

Expand All @@ -79,6 +81,10 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
function f1<T>(x: T, y: NonNullable<T>) {
x = y;
y = x; // Error
~
!!! error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
!!! error TS2322: Type 'T' is not assignable to type '{}'.
!!! related TS2208 tests/cases/conformance/types/conditional/conditionalTypes1.ts:10:13: This type parameter probably needs an `extends object` constraint.
}

function f2<T extends string | undefined>(x: T, y: NonNullable<T>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(2,5): error TS2339: Property 'toString' does not exist on type 'T'.
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(15,6): error TS2345: Argument of type 'T' is not assignable to parameter of type '{}'.
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(16,6): error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record<string, any>'.
tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(17,5): error TS2339: Property 'toString' does not exist on type 'T'.


==== tests/cases/compiler/genericUnboundedTypeParamAssignability.ts (2 errors) ====
==== tests/cases/compiler/genericUnboundedTypeParamAssignability.ts (4 errors) ====
function f1<T>(o: T) {
o.toString(); // error
~~~~~~~~
Expand All @@ -20,7 +22,13 @@ tests/cases/compiler/genericUnboundedTypeParamAssignability.ts(17,5): error TS23
function user<T>(t: T) {
f1(t);
f2(t); // error in strict, unbounded T doesn't satisfy the constraint
~
!!! error TS2345: Argument of type 'T' is not assignable to parameter of type '{}'.
!!! related TS2208 tests/cases/compiler/genericUnboundedTypeParamAssignability.ts:13:15: This type parameter probably needs an `extends object` constraint.
f3(t); // error in strict, unbounded T doesn't satisfy the constraint
~
!!! error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record<string, any>'.
!!! related TS2208 tests/cases/compiler/genericUnboundedTypeParamAssignability.ts:13:15: This type parameter probably needs an `extends object` constraint.
t.toString(); // error, for the same reason as f1()
~~~~~~~~
!!! error TS2339: Property 'toString' does not exist on type 'T'.
Expand Down
Loading

0 comments on commit a16b1ad

Please sign in to comment.