Skip to content

Commit db2aea0

Browse files
sandersntypescript-bot
authored andcommitted
Cherry-pick PR microsoft#33213 into release-3.6
Component commits: cc1dc3b someTypeRelatedToType now passes isIntersectionConstituent cf3eadc Merge branch 'master' into fix-missed-intersection-constituent-threading f10fe38 Fix [][] lint
1 parent 49b910e commit db2aea0

6 files changed

+176
-10
lines changed

src/compiler/checker.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -12846,7 +12846,7 @@ namespace ts {
1284612846
// and we need to handle "each" relations before "some" relations for the same kind of type.
1284712847
if (source.flags & TypeFlags.Union) {
1284812848
result = relation === comparableRelation ?
12849-
someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive)) :
12849+
someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), isIntersectionConstituent) :
1285012850
eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive));
1285112851
}
1285212852
else {
@@ -12884,7 +12884,7 @@ namespace ts {
1288412884
//
1288512885
// - For a primitive type or type parameter (such as 'number = A & B') there is no point in
1288612886
// breaking the intersection apart.
12887-
result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false);
12887+
result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false, /*isIntersectionConstituent*/ true);
1288812888
}
1288912889
if (!result && (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable)) {
1289012890
if (result = recursiveTypeRelatedTo(source, target, reportErrors, isIntersectionConstituent)) {
@@ -13163,14 +13163,14 @@ namespace ts {
1316313163
return result;
1316413164
}
1316513165

13166-
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
13166+
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, isIntersectionConstituent: boolean): Ternary {
1316713167
const sourceTypes = source.types;
1316813168
if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) {
1316913169
return Ternary.True;
1317013170
}
1317113171
const len = sourceTypes.length;
1317213172
for (let i = 0; i < len; i++) {
13173-
const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1);
13173+
const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1, /*headMessage*/ undefined, isIntersectionConstituent);
1317413174
if (related) {
1317513175
return related;
1317613176
}
@@ -21542,13 +21542,13 @@ namespace ts {
2154221542
checkMode: CheckMode,
2154321543
reportErrors: boolean,
2154421544
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
21545-
) {
21545+
): ReadonlyArray<Diagnostic> | undefined {
2154621546

2154721547
const errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } = { errors: undefined, skipLogging: true };
2154821548
if (isJsxOpeningLikeElement(node)) {
2154921549
if (!checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors, containingMessageChain, errorOutputContainer)) {
2155021550
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors");
21551-
return errorOutputContainer.errors || [];
21551+
return errorOutputContainer.errors || emptyArray;
2155221552
}
2155321553
return undefined;
2155421554
}
@@ -21563,7 +21563,7 @@ namespace ts {
2156321563
const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1;
2156421564
if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer)) {
2156521565
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors");
21566-
return errorOutputContainer.errors || [];
21566+
return errorOutputContainer.errors || emptyArray;
2156721567
}
2156821568
}
2156921569
const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
@@ -21581,7 +21581,7 @@ namespace ts {
2158121581
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containingMessageChain, errorOutputContainer)) {
2158221582
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors");
2158321583
maybeAddMissingAwaitInfo(arg, checkArgType, paramType);
21584-
return errorOutputContainer.errors || [];
21584+
return errorOutputContainer.errors || emptyArray;
2158521585
}
2158621586
}
2158721587
}
@@ -21591,7 +21591,7 @@ namespace ts {
2159121591
if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) {
2159221592
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors");
2159321593
maybeAddMissingAwaitInfo(errorNode, spreadType, restType);
21594-
return errorOutputContainer.errors || [];
21594+
return errorOutputContainer.errors || emptyArray;
2159521595
}
2159621596
}
2159721597
return undefined;
@@ -21982,7 +21982,7 @@ namespace ts {
2198221982
}
2198321983
}
2198421984
else {
21985-
const allDiagnostics: DiagnosticRelatedInformation[][] = [];
21985+
const allDiagnostics: (readonly DiagnosticRelatedInformation[])[] = [];
2198621986
let max = 0;
2198721987
let min = Number.MAX_VALUE;
2198821988
let minIndex = 0;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx(10,21): error TS2304: Cannot find name 'React'.
2+
3+
4+
==== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx (1 errors) ====
5+
interface F<P> {
6+
(props: P & { children?: boolean }): void;
7+
propTypes: { [K in keyof P]: null extends P ? K : K };
8+
}
9+
declare function g(C: F<unknown>): string;
10+
export function wu<CP extends { o: object }>(CC: F<CP>) {
11+
class WU {
12+
m() {
13+
g(CC)
14+
return <CC {...(null as unknown as CP)} />;
15+
~~
16+
!!! error TS2304: Cannot find name 'React'.
17+
}
18+
}
19+
}
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//// [quickIntersectionCheckCorrectlyCachesErrors.tsx]
2+
interface F<P> {
3+
(props: P & { children?: boolean }): void;
4+
propTypes: { [K in keyof P]: null extends P ? K : K };
5+
}
6+
declare function g(C: F<unknown>): string;
7+
export function wu<CP extends { o: object }>(CC: F<CP>) {
8+
class WU {
9+
m() {
10+
g(CC)
11+
return <CC {...(null as unknown as CP)} />;
12+
}
13+
}
14+
}
15+
16+
17+
//// [quickIntersectionCheckCorrectlyCachesErrors.js]
18+
"use strict";
19+
var __assign = (this && this.__assign) || function () {
20+
__assign = Object.assign || function(t) {
21+
for (var s, i = 1, n = arguments.length; i < n; i++) {
22+
s = arguments[i];
23+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
24+
t[p] = s[p];
25+
}
26+
return t;
27+
};
28+
return __assign.apply(this, arguments);
29+
};
30+
exports.__esModule = true;
31+
function wu(CC) {
32+
var WU = /** @class */ (function () {
33+
function WU() {
34+
}
35+
WU.prototype.m = function () {
36+
g(CC);
37+
return React.createElement(CC, __assign({}, null));
38+
};
39+
return WU;
40+
}());
41+
}
42+
exports.wu = wu;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
=== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx ===
2+
interface F<P> {
3+
>F : Symbol(F, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 0))
4+
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))
5+
6+
(props: P & { children?: boolean }): void;
7+
>props : Symbol(props, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 1, 5))
8+
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))
9+
>children : Symbol(children, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 1, 17))
10+
11+
propTypes: { [K in keyof P]: null extends P ? K : K };
12+
>propTypes : Symbol(F.propTypes, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 1, 46))
13+
>K : Symbol(K, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 2, 18))
14+
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))
15+
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))
16+
>K : Symbol(K, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 2, 18))
17+
>K : Symbol(K, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 2, 18))
18+
}
19+
declare function g(C: F<unknown>): string;
20+
>g : Symbol(g, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 3, 1))
21+
>C : Symbol(C, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 4, 19))
22+
>F : Symbol(F, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 0))
23+
24+
export function wu<CP extends { o: object }>(CC: F<CP>) {
25+
>wu : Symbol(wu, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 4, 42))
26+
>CP : Symbol(CP, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 19))
27+
>o : Symbol(o, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 31))
28+
>CC : Symbol(CC, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 45))
29+
>F : Symbol(F, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 0))
30+
>CP : Symbol(CP, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 19))
31+
32+
class WU {
33+
>WU : Symbol(WU, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 57))
34+
35+
m() {
36+
>m : Symbol(WU.m, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 6, 14))
37+
38+
g(CC)
39+
>g : Symbol(g, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 3, 1))
40+
>CC : Symbol(CC, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 45))
41+
42+
return <CC {...(null as unknown as CP)} />;
43+
>CC : Symbol(CC, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 45))
44+
>CP : Symbol(CP, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 19))
45+
}
46+
}
47+
}
48+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
=== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx ===
2+
interface F<P> {
3+
(props: P & { children?: boolean }): void;
4+
>props : P & { children?: boolean; }
5+
>children : boolean
6+
7+
propTypes: { [K in keyof P]: null extends P ? K : K };
8+
>propTypes : { [K in keyof P]: null extends P ? K : K; }
9+
>null : null
10+
}
11+
declare function g(C: F<unknown>): string;
12+
>g : (C: F<unknown>) => string
13+
>C : F<unknown>
14+
15+
export function wu<CP extends { o: object }>(CC: F<CP>) {
16+
>wu : <CP extends { o: object; }>(CC: F<CP>) => void
17+
>o : object
18+
>CC : F<CP>
19+
20+
class WU {
21+
>WU : WU
22+
23+
m() {
24+
>m : () => any
25+
26+
g(CC)
27+
>g(CC) : string
28+
>g : (C: F<unknown>) => string
29+
>CC : F<CP>
30+
31+
return <CC {...(null as unknown as CP)} />;
32+
><CC {...(null as unknown as CP)} /> : any
33+
>CC : F<CP>
34+
>(null as unknown as CP) : CP
35+
>null as unknown as CP : CP
36+
>null as unknown : unknown
37+
>null : null
38+
}
39+
}
40+
}
41+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @jsx: react
2+
// @filename: quickIntersectionCheckCorrectlyCachesErrors.tsx
3+
interface F<P> {
4+
(props: P & { children?: boolean }): void;
5+
propTypes: { [K in keyof P]: null extends P ? K : K };
6+
}
7+
declare function g(C: F<unknown>): string;
8+
export function wu<CP extends { o: object }>(CC: F<CP>) {
9+
class WU {
10+
m() {
11+
g(CC)
12+
return <CC {...(null as unknown as CP)} />;
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)