10000 Merge pull request #19107 from Microsoft/fixRecursiveCallbacks · microsoft/TypeScript@6cf41ae · GitHub
[go: up one dir, main page]

Skip to content

Commit 6cf41ae

Browse files
authored
Merge pull request #19107 from Microsoft/fixRecursiveCallbacks
Fix checking of recursive callback types
2 parents 562a046 + 38cec12 commit 6cf41ae

File tree

6 files changed

+117
-3
lines changed

6 files changed

+117
-3
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8610,16 +8610,16 @@ namespace ts {
86108610
for (let i = 0; i < checkCount; i++) {
86118611
const sourceType = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source);
86128612
const targetType = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target);
8613-
const sourceSig = getSingleCallSignature(getNonNullableType(sourceType));
8614-
const targetSig = getSingleCallSignature(getNonNullableType(targetType));
86158613
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
86168614
// how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
86178615
// they naturally relate only contra-variantly). However, if the source and target parameters both have
8618-
// function types with a single call signature, we known we are relating two callback parameters. In
8616+
// function types with a single call signature, we know we are relating two callback parameters. In
86198617
// that case it is sufficient to only relate the parameters of the signatures co-variantly because,
86208618
// similar to return values, callback parameters are output positions. This means that a Promise<T>,
86218619
// where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant)
86228620
// with respect to T.
8621+
const sourceSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
8622+
const targetSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(targetType));
86238623
const callbacks = sourceSig && targetSig && !sourceSig.typePredicate && !targetSig.typePredicate &&
86248624
(getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable);
86258625
const related = callbacks ?
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tests/cases/compiler/mutuallyRecursiveCallbacks.ts(7,1): error TS2322: Type '<T>(bar: Bar<T>) => void' is not assignable to type 'Bar<{}>'.
2+
Types of parameters 'bar' and 'foo' are incompatible.
3+
Types of parameters 'bar' and 'foo' are incompatible.
4+
Type 'Foo<{}>' is not assignable to type 'Bar<{}>'.
5+
Types of parameters 'bar' and 'foo' are incompatible.
6+
Type 'void' is not assignable to type 'Foo<{}>'.
7+
8+
9+
==== tests/cases/compiler/mutuallyRecursiveCallbacks.ts (1 errors) ====
10+
// Repro from #18277
11+
12+
interface Foo<T> { (bar: Bar<T>): void };
13+
type Bar<T> = (foo: Foo<T>) => Foo<T>;
14+
declare function foo<T>(bar: Bar<T>): void;
15+
declare var bar: Bar<{}>;
16+
bar = foo;
17+
~~~
18+
!!! error TS2322: Type '<T>(bar: Bar<T>) => void' is not assignable to type 'Bar<{}>'.
19+
!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible.
20+
!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible.
21+
!!! error TS2322: Type 'Foo<{}>' is not assignable to type 'Bar<{}>'.
22+
!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible.
23+
!!! error TS2322: Type 'void' is not assignable to type 'Foo<{}>'.
24+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//// [mutuallyRecursiveCallbacks.ts]
2+
// Repro from #18277
3+
4+
interface Foo<T> { (bar: Bar<T>): void };
5+
type Bar<T> = (foo: Foo<T>) => Foo<T>;
6+
declare function foo<T>(bar: Bar<T>): void;
7+
declare var bar: Bar<{}>;
8+
bar = foo;
9+
10+
11+
//// [mutuallyRecursiveCallbacks.js]
12+
// Repro from #18277
13+
;
14+
bar = foo;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/mutuallyRecursiveCallbacks.ts ===
2+
// Repro from #18277
3+
4+
interface Foo<T> { (bar: Bar<T>): void };
5+
>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0))
6+
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 2, 14))
7+
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 20))
8+
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
9+
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 2, 14))
10+
11+
type Bar<T> = (foo: Foo<T>) => Foo<T>;
12+
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
13+
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9))
14+
>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 15))
15+
>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0))
16+
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9))
17+
>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0))
18+
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9))
19+
20+
declare function foo<T>(bar: Bar<T>): void;
21+
>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 38))
22+
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 4, 21))
23+
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 4, 24))
24+
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
25+
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 4, 21))
26+
27+
declare var bar: Bar<{}>;
28+
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 5, 11))
29+
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
30+
31+
bar = foo;
32+
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 5, 11))
33+
>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 38))
34+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/compiler/mutuallyRecursiveCallbacks.ts ===
2+
// Repro from #18277
3+
4+
interface Foo<T> { (bar: Bar<T>): void };
5+
>Foo : Foo<T>
6+
>T : T
7+
>bar : Bar<T>
8+
>Bar : Bar<T>
9+
>T : T
10+
11+
type Bar<T> = (foo: Foo<T>) => Foo<T>;
12+
>Bar : Bar<T>
13+
>T : T
14+
>foo : Foo<T>
15+
>Foo : Foo<T>
16+
>T : T
17+
>Foo : Foo<T>
18+
>T : T
19+
20+
declare function foo<T>(bar: Bar<T>): void;
21+
>foo : <T>(bar: Bar<T>) => void
22+
>T : T
23+
>bar : Bar<T>
24+
>Bar : Bar<T>
25+
>T : T
26+
27+
declare var bar: Bar<{}>;
28+
>bar : Bar<{}>
29+
>Bar : Bar<T>
30+
31+
bar = foo;
32+
>bar = foo : <T>(bar: Bar<T>) => void
33+
>bar : Bar<{}>
34+
>foo : <T>(bar: Bar<T>) => void
35+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Repro from #18277
2+
3+
interface Foo<T> { (bar: Bar<T>): void };
4+
type Bar<T> = (foo: Foo<T>) => Foo<T>;
5+
declare function foo<T>(bar: Bar<T>): void;
6+
declare var bar: Bar<{}>;
7+
bar = foo;

0 commit comments

Comments
 (0)
0