Skip to content

Commit 5a1d308

Browse files
authored
Combine multiple overloads into a single contextual signature (#42620)
* When noImplicitAny is set, combine multiple contextual overloads into a single signature, rather than producing `any` and an error * Amalgamate intersection composite signature return types as intersections, rather than the prior exclusively union behavior * Add another example from an issue, albeit slightly modified * Fix newlines, add test from DT * Interior remodelling
1 parent c7fa6e0 commit 5a1d308

16 files changed

+879
-145
lines changed

src/compiler/checker.ts

+134-25
Large diffs are not rendered by default.

src/compiler/types.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -5548,7 +5548,9 @@ namespace ts {
55485548
/* @internal */
55495549
mapper?: TypeMapper; // Instantiation mapper
55505550
/* @internal */
5551-
unionSignatures?: Signature[]; // Underlying signatures of a union signature
5551+
compositeSignatures?: Signature[]; // Underlying signatures of a union/intersection signature
5552+
/* @internal */
5553+
compositeKind?: TypeFlags; // TypeFlags.Union if the underlying signatures are from union members, otherwise TypeFlags.Intersection
55525554
/* @internal */
55535555
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
55545556
/* @internal */

tests/baselines/reference/callsOnComplexSignatures.errors.txt

-110
This file was deleted.

tests/baselines/reference/callsOnComplexSignatures.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ function test3(items: string[] | number[]) {
100100
>items.forEach : ((callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void) | ((callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void)
101101
>items : string[] | number[]
102102
>forEach : ((callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void) | ((callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void)
103-
>item => console.log(item) : (item: any) => void
104-
>item : any
103+
>item => console.log(item) : (item: string | number) => void
104+
>item : string | number
105105
>console.log(item) : void
106106
>console.log : (...data: any[]) => void
107107
>console : Console
108108
>log : (...data: any[]) => void
109-
>item : any
109+
>item : string | number
110110
}
111111

112112
function test4(

tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ declare var connect: Connect;
5656

5757
const myStoreConnect: Connect = function(
5858
>myStoreConnect : Connect
59-
>function( mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options: unknown = {},) { return connect( mapStateToProps, mapDispatchToProps, mergeProps, options, );} : (mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options?: unknown) => InferableComponentEnhancerWithProps<unknown, unknown>
59+
>function( mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options: unknown = {},) { return connect( mapStateToProps, mapDispatchToProps, mergeProps, options, );} : <TStateProps, TOwnProps>(mapStateToProps?: any, mapDispatchToProps?: any, mergeProps?: any, options?: unknown) => InferableComponentEnhancerWithProps<TStateProps, Omit<P, Extract<keyof TStateProps, keyof P>> & TOwnProps>
6060

6161
mapStateToProps?: any,
6262
>mapStateToProps : any
@@ -73,7 +73,7 @@ const myStoreConnect: Connect = function(
7373

7474
) {
7575
return connect(
76-
>connect( mapStateToProps, mapDispatchToProps, mergeProps, options, ) : InferableComponentEnhancerWithProps<unknown, unknown>
76+
>connect( mapStateToProps, mapDispatchToProps, mergeProps, options, ) : InferableComponentEnhancerWithProps<TStateProps, Omit<P, Extract<keyof TStateProps, keyof P>> & TOwnProps>
7777
>connect : Connect
7878

7979
mapStateToProps,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//// [tests/cases/compiler/contextualOverloadListFromArrayUnion.ts] ////
2+
3+
//// [one.ts]
4+
declare const y: never[] | string[];
5+
export const yThen = y.map(item => item.length);
6+
//// [two.ts]
7+
declare const y: number[][] | string[];
8+
export const yThen = y.map(item => item.length);
9+
//// [three.ts]
10+
// #42504
11+
interface ResizeObserverCallback {
12+
(entries: ResizeObserverEntry[], observer: ResizeObserver): void;
13+
}
14+
interface ResizeObserverCallback { // duplicate for effect
15+
(entries: ResizeObserverEntry[], observer: ResizeObserver): void;
16+
}
17+
18+
const resizeObserver = new ResizeObserver(([entry]) => {
19+
entry
20+
});
21+
// comment in #35501
22+
interface Callback<T> {
23+
(error: null, result: T): unknown
24+
(error: Error, result: null): unknown
25+
}
26+
27+
interface Task<T> {
28+
(callback: Callback<T>): unknown
29+
}
30+
31+
export function series<T>(tasks: Task<T>[], callback: Callback<T[]>): void {
32+
let index = 0
33+
let results: T[] = []
34+
35+
function next() {
36+
let task = tasks[index]
37+
if (!task) {
38+
callback(null, results)
39+
} else {
40+
task((error, result) => {
41+
if (error) {
42+
callback(error, null)
43+
} else {
44+
// must use postfix-!, since `error` and `result` don't have a
45+
// causal relationship when the overloads are combined
46+
results.push(result!)
47+
next()
48+
}
49+
})
50+
}
51+
}
52+
next()
53+
}
54+
55+
series([
56+
cb => setTimeout(() => cb(null, 1), 300),
57+
cb => setTimeout(() => cb(null, 2), 200),
58+
cb => setTimeout(() => cb(null, 3), 100),
59+
], (error, results) => {
60+
if (error) {
61+
console.error(error)
62+
} else {
63+
console.log(results)
64+
}
65+
})
66+
67+
68+
//// [one.js]
69+
export const yThen = y.map(item => item.length);
70+
//// [two.js]
71+
export const yThen = y.map(item => item.length);
72+
//// [three.js]
73+
const resizeObserver = new ResizeObserver(([entry]) => {
74+
entry;
75+
});
76+
export function series(tasks, callback) {
77+
let index = 0;
78+
let results = [];
79+
function next() {
80+
let task = tasks[index];
81+
if (!task) {
82+
callback(null, results);
83+
}
84+
else {
85+
task((error, result) => {
86+
if (error) {
87+
callback(error, null);
88+
}
89+
else {
90+
// must use postfix-!, since `error` and `result` don't have a
91+
// causal relationship when the overloads are combined
92+
results.push(result);
93+
next();
94+
}
95+
});
96+
}
97+
}
98+
next();
99+
}
100+
series([
101+
cb => setTimeout(() => cb(null, 1), 300),
102+
cb => setTimeout(() => cb(null, 2), 200),
103+
cb => setTimeout(() => cb(null, 3), 100),
104+
], (error, results) => {
105+
if (error) {
106+
console.error(error);
107+
}
108+
else {
109+
console.log(results);
110+
}
111+
});

0 commit comments

Comments
 (0)