Skip to content

Commit

Permalink
Limit to single overlappy type to improve back other errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist committed Feb 25, 2024
1 parent c605f6b commit e9d136a
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 21 deletions.
10 changes: 5 additions & 5 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21985,7 +21985,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
if (reportErrors) {
// Elaborate only if we can find a best matching type in the target
const bestMatchingType = getBestMatchingType(source, target, isRelatedTo);
const bestMatchingType = getBestMatchingType(source, target, isRelatedTo, /*singleOverlappy*/ true);
if (bestMatchingType) {
isRelatedTo(source, bestMatchingType, RecursionFlags.Target, /*reportErrors*/ true, /*headMessage*/ undefined, intersectionState);
}
Expand Down Expand Up @@ -23712,11 +23712,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return getPropertiesOfType(type).filter(targetProp => containsMissingType(getTypeOfSymbol(targetProp)));
}

function getBestMatchingType(source: Type, target: UnionOrIntersectionType, isRelatedTo = compareTypesAssignable) {
function getBestMatchingType(source: Type, target: UnionOrIntersectionType, isRelatedTo = compareTypesAssignable, singleOverlappy = false) {
return findMatchingDiscriminantType(source, target, isRelatedTo) ||
findMatchingTypeReferenceOrTypeAliasReference(source, target) ||
findBestTypeForInvokable(source, target) ||
findMostOverlappyType(source, filterTypesForObjectLiteralMatch(source, target));
findMostOverlappyType(source, filterTypesForObjectLiteralMatch(source, target), singleOverlappy);
}

function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: (readonly [() => Type, __String])[], related: (source: Type, target: Type) => boolean | Ternary) {
Expand Down Expand Up @@ -50924,7 +50924,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}

function findMostOverlappyType(source: Type, target: Type) {
function findMostOverlappyType(source: Type, target: Type, singleOverlappy: boolean) {
if (!(target.flags & TypeFlags.UnionOrIntersection)) {
return target;
}
Expand Down Expand Up @@ -50954,7 +50954,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
}
return bestMatches.length ? getUnionType(bestMatches) : undefined;
return bestMatches.length ? singleOverlappy ? bestMatches[0] : getUnionType(bestMatches) : undefined;
}

function filterPrimitivesIfContainsNonPrimitive(type: UnionType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
assignmentCompatWithDiscriminatedUnion.ts(44,5): error TS2322: Type 'S' is not assignable to type 'T'.
Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; } | { a: 1; b: 2 | 4; }'.
Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; }'.
Types of property 'a' are incompatible.
Type '0 | 2' is not assignable to type '0'.
Type '2' is not assignable to type '0'.
assignmentCompatWithDiscriminatedUnion.ts(58,5): error TS2322: Type 'S' is not assignable to type 'T'.
Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; } | { a: 2; b: 4 | 3; c: string; }'.
Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; }'.
Types of property 'a' are incompatible.
Type '0 | 2' is not assignable to type '0'.
Type '2' is not assignable to type '0'.
assignmentCompatWithDiscriminatedUnion.ts(82,5): error TS2322: Type 'S' is not assignable to type 'T'.


Expand Down Expand Up @@ -53,6 +61,10 @@ assignmentCompatWithDiscriminatedUnion.ts(82,5): error TS2322: Type 'S' is not a
~
!!! error TS2322: Type 'S' is not assignable to type 'T'.
!!! error TS2322: Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; } | { a: 1; b: 2 | 4; }'.
!!! error TS2322: Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type '0 | 2' is not assignable to type '0'.
!!! error TS2322: Type '2' is not assignable to type '0'.
}

// Unmatched non-discriminants
Expand All @@ -70,6 +82,10 @@ assignmentCompatWithDiscriminatedUnion.ts(82,5): error TS2322: Type 'S' is not a
~
!!! error TS2322: Type 'S' is not assignable to type 'T'.
!!! error TS2322: Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; } | { a: 2; b: 4 | 3; c: string; }'.
!!! error TS2322: Type 'S' is not assignable to type '{ a: 0; b: 4 | 1; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type '0 | 2' is not assignable to type '0'.
!!! error TS2322: Type '2' is not assignable to type '0'.
}

// Maximum discriminant combinations
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/bigintWithLib.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ bigintWithLib.ts(19,33): error TS2769: No overload matches this call.
Type 'number' is not assignable to type 'bigint'.
Overload 3 of 3, '(buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigInt64Array', gave the following error.
Argument of type 'number[]' is not assignable to parameter of type 'ArrayBufferLike'.
Type 'number[]' is not assignable to type 'ArrayBuffer | SharedArrayBuffer'.
Type 'number[]' is missing the following properties from type 'ArrayBuffer': byteLength, [Symbol.toStringTag]
bigintWithLib.ts(24,13): error TS2540: Cannot assign to 'length' because it is a read-only property.
bigintWithLib.ts(31,35): error TS2769: No overload matches this call.
Overload 1 of 3, '(length?: number): BigUint64Array', gave the following error.
Expand Down Expand Up @@ -60,7 +60,7 @@ bigintWithLib.ts(46,26): error TS2345: Argument of type 'number' is not assignab
!!! error TS2769: Type 'number' is not assignable to type 'bigint'.
!!! error TS2769: Overload 3 of 3, '(buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigInt64Array', gave the following error.
!!! error TS2769: Argument of type 'number[]' is not assignable to parameter of type 'ArrayBufferLike'.
!!! error TS2769: Type 'number[]' is not assignable to type 'ArrayBuffer | SharedArrayBuffer'.
!!! error TS2769: Type 'number[]' is missing the following properties from type 'ArrayBuffer': byteLength, [Symbol.toStringTag]
bigIntArray = new BigInt64Array(new ArrayBuffer(80));
bigIntArray = new BigInt64Array(new ArrayBuffer(80), 8);
bigIntArray = new BigInt64Array(new ArrayBuffer(80), 8, 3);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
contextualTypeWithUnionTypeObjectLiteral.ts(14,5): error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'.
Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'.
Type '{ prop: string | number; }' is not assignable to type '{ prop: string; }'.
Types of property 'prop' are incompatible.
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
contextualTypeWithUnionTypeObjectLiteral.ts(20,5): error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'.
Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'.
Property 'anotherP' is missing in type '{ prop: string | number; }' but required in type '{ prop: string; anotherP: string; }'.
contextualTypeWithUnionTypeObjectLiteral.ts(22,5): error TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
contextualTypeWithUnionTypeObjectLiteral.ts(26,5): error TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
contextualTypeWithUnionTypeObjectLiteral.ts(29,5): error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'.
Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'.
Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; }'.
Types of property 'prop' are incompatible.
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
contextualTypeWithUnionTypeObjectLiteral.ts(58,5): error TS2322: Type '(a: string, b: number) => string | number' is not assignable to type '((a: string, b: number) => string) | ((a: string, b: number) => number)'.
Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => string'.
Type 'string | number' is not assignable to type 'string'.
Expand All @@ -31,7 +37,10 @@ contextualTypeWithUnionTypeObjectLiteral.ts(58,5): error TS2322: Type '(a: strin
var objStrOrNum3: { prop: string } | { prop: number } = {
~~~~~~~~~~~~
!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'.
!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'.
!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; }'.
!!! error TS2322: Types of property 'prop' are incompatible.
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
prop: strOrNumber
};
var objStrOrNum4: { prop: string | number } = {
Expand All @@ -40,7 +49,8 @@ contextualTypeWithUnionTypeObjectLiteral.ts(58,5): error TS2322: Type '(a: strin
var objStrOrNum5: { prop: string; anotherP: string; } | { prop: number } = { prop: strOrNumber };
~~~~~~~~~~~~
!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'.
!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'.
!!! error TS2322: Property 'anotherP' is missing in type '{ prop: string | number; }' but required in type '{ prop: string; anotherP: string; }'.
!!! related TS2728 contextualTypeWithUnionTypeObjectLiteral.ts:20:35: 'anotherP' is declared here.
var objStrOrNum6: { prop: string; anotherP: string; } | { prop: number } = {
prop: strOrNumber,
~~~~
Expand All @@ -60,7 +70,10 @@ contextualTypeWithUnionTypeObjectLiteral.ts(58,5): error TS2322: Type '(a: strin
var objStrOrNum8: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = {
~~~~~~~~~~~~
!!! error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'.
!!! error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'.
!!! error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; }'.
!!! error TS2322: Types of property 'prop' are incompatible.
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
prop: strOrNumber,
anotherP: str,
anotherP1: num
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ excessPropertyCheckWithUnions.ts(33,28): error TS2353: Object literal may only s
excessPropertyCheckWithUnions.ts(34,26): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ tag: "A"; x: string; } | { tag: "A"; y: number; }'.
excessPropertyCheckWithUnions.ts(37,1): error TS2322: Type '{ tag: "A"; }' is not assignable to type 'Ambiguous'.
Type '{ tag: "A"; }' is not assignable to type '{ tag: "A"; x: string; } | { tag: "A"; y: number; }'.
Property 'x' is missing in type '{ tag: "A"; }' but required in type '{ tag: "A"; x: string; }'.
excessPropertyCheckWithUnions.ts(38,19): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ tag: "A"; x: string; } | { tag: "A"; y: number; }'.
excessPropertyCheckWithUnions.ts(47,35): error TS2353: Object literal may only specify known properties, and 'second' does not exist in type '{ a: 1; b: 1; first: string; }'.
excessPropertyCheckWithUnions.ts(48,35): error TS2353: Object literal may only specify known properties, and 'third' does not exist in type '{ a: 1; b: 1; first: string; }'.
Expand Down Expand Up @@ -69,6 +70,8 @@ excessPropertyCheckWithUnions.ts(112,63): error TS2322: Type 'string' is not ass
~~~
!!! error TS2322: Type '{ tag: "A"; }' is not assignable to type 'Ambiguous'.
!!! error TS2322: Type '{ tag: "A"; }' is not assignable to type '{ tag: "A"; x: string; } | { tag: "A"; y: number; }'.
!!! error TS2322: Property 'x' is missing in type '{ tag: "A"; }' but required in type '{ tag: "A"; x: string; }'.
!!! related TS2728 excessPropertyCheckWithUnions.ts:16:5: 'x' is declared here.
amb = { tag: "A", z: true }
~
!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ tag: "A"; x: string; } | { tag: "A"; y: number; }'.
Expand Down
4 changes: 4 additions & 0 deletions tests/baselines/reference/genericRestParameters3.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ genericRestParameters3.ts(17,11): error TS2345: Argument of type '[10]' is not a
Type '[10]' is not assignable to type '[string]'.
Type 'number' is not assignable to type 'string'.
genericRestParameters3.ts(18,1): error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'.
Type '[]' is not assignable to type '[string]'.
Source has 0 element(s) but target requires 1.
genericRestParameters3.ts(23,1): error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
Types of parameters 'y' and 'args' are incompatible.
Type '[string] | [number, boolean]' is not assignable to type '[y: string]'.
Expand Down Expand Up @@ -57,6 +59,8 @@ genericRestParameters3.ts(59,5): error TS2345: Argument of type '["what"]' is no
f1("foo"); // Error
~~~~~~~~~
!!! error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'.
!!! error TS2345: Type '[]' is not assignable to type '[string]'.
!!! error TS2345: Source has 0 element(s) but target requires 1.

f2 = f1;
f3 = f1;
Expand Down
26 changes: 18 additions & 8 deletions tests/baselines/reference/intersectionAndUnionTypes.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@ intersectionAndUnionTypes.ts(28,1): error TS2322: Type '(A & B) | (C & D)' is no
intersectionAndUnionTypes.ts(29,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C | D'.
Type 'A & B' is not assignable to type 'C | D'.
intersectionAndUnionTypes.ts(31,1): error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
Type 'A & B' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'A & B' is not assignable to type 'A & C'.
Type 'A & B' is not assignable to type 'C'.
intersectionAndUnionTypes.ts(32,1): error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
Type 'A' is not assignable to type '(A | B) & (C | D)'.
Type 'A' is not assignable to type '(A & C) | (A & D)'.
Type 'A' is not assignable to type 'A & C'.
Property 'c' is missing in type 'A' but required in type 'C'.
intersectionAndUnionTypes.ts(33,1): error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
Type 'C & D' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'C & D' is not assignable to type 'A & C'.
Type 'C & D' is not assignable to type 'A'.
intersectionAndUnionTypes.ts(34,1): error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
Type 'C' is not assignable to type '(A | B) & (C | D)'.
Type 'C' is not assignable to type '(A & C) | (B & C)'.
Type 'C' is not assignable to type 'A & C'.
Property 'a' is missing in type 'C' but required in type 'A'.
intersectionAndUnionTypes.ts(35,1): error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
Type 'A & C' is not assignable to type 'A & B'.
Property 'b' is missing in type 'A & C' but required in type 'B'.
Expand Down Expand Up @@ -105,21 +109,27 @@ intersectionAndUnionTypes.ts(37,1): error TS2322: Type '(A | B) & (C | D)' is no
y = anb;
~
!!! error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'A & B' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'A & B' is not assignable to type 'A & C'.
!!! error TS2322: Type 'A & B' is not assignable to type 'C'.
y = aob;
~
!!! error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'A' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'A' is not assignable to type '(A & C) | (A & D)'.
!!! error TS2322: Type 'A' is not assignable to type 'A & C'.
!!! error TS2322: Property 'c' is missing in type 'A' but required in type 'C'.
!!! related TS2728 intersectionAndUnionTypes.ts:3:15: 'c' is declared here.
y = cnd;
~
!!! error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'C & D' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'C & D' is not assignable to type 'A & C'.
!!! error TS2322: Type 'C & D' is not assignable to type 'A'.
y = cod;
~
!!! error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'C' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'C' is not assignable to type '(A & C) | (B & C)'.
!!! error TS2322: Type 'C' is not assignable to type 'A & C'.
!!! error TS2322: Property 'a' is missing in type 'C' but required in type 'A'.
!!! related TS2728 intersectionAndUnionTypes.ts:1:15: 'a' is declared here.
anb = y;
~~~
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
Expand Down
6 changes: 6 additions & 0 deletions tests/baselines/reference/jsxComponentTypeErrors.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jsxComponentTypeErrors.tsx(28,16): error TS2786: 'MixedComponent' cannot be used
Its element type 'ClassComponent | { type: string | undefined; }' is not a valid JSX element.
Type 'ClassComponent' is not assignable to type 'Element | ElementClass | null'.
Type 'ClassComponent' is not assignable to type 'Element | ElementClass'.
Type 'ClassComponent' is not assignable to type 'Element'.
Types of property 'type' are incompatible.
Type 'string' is not assignable to type '"element"'.
jsxComponentTypeErrors.tsx(37,16): error TS2786: 'obj.MemberFunctionComponent' cannot be used as a JSX component.
Its return type '{}' is not a valid JSX element.
Property 'type' is missing in type '{}' but required in type 'Element'.
Expand Down Expand Up @@ -80,6 +83,9 @@ jsxComponentTypeErrors.tsx(38,16): error TS2786: 'obj. MemberClassComponent' can
!!! error TS2786: Its element type 'ClassComponent | { type: string | undefined; }' is not a valid JSX element.
!!! error TS2786: Type 'ClassComponent' is not assignable to type 'Element | ElementClass | null'.
!!! error TS2786: Type 'ClassComponent' is not assignable to type 'Element | ElementClass'.
!!! error TS2786: Type 'ClassComponent' is not assignable to type 'Element'.
!!! error TS2786: Types of property 'type' are incompatible.
!!! error TS2786: Type 'string' is not assignable to type '"element"'.

const obj = {
MemberFunctionComponent() {
Expand Down

0 comments on commit e9d136a

Please sign in to comment.