mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-09 20:51:43 -06:00
Merge pull request #19107 from Microsoft/fixRecursiveCallbacks
Fix checking of recursive callback types
This commit is contained in:
commit
6cf41ae882
@ -8610,16 +8610,16 @@ namespace ts {
|
||||
for (let i = 0; i < checkCount; i++) {
|
||||
const sourceType = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source);
|
||||
const targetType = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target);
|
||||
const sourceSig = getSingleCallSignature(getNonNullableType(sourceType));
|
||||
const targetSig = getSingleCallSignature(getNonNullableType(targetType));
|
||||
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
|
||||
// how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
|
||||
// they naturally relate only contra-variantly). However, if the source and target parameters both have
|
||||
// function types with a single call signature, we known we are relating two callback parameters. In
|
||||
// function types with a single call signature, we know we are relating two callback parameters. In
|
||||
// that case it is sufficient to only relate the parameters of the signatures co-variantly because,
|
||||
// similar to return values, callback parameters are output positions. This means that a Promise<T>,
|
||||
// where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant)
|
||||
// with respect to T.
|
||||
const sourceSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
|
||||
const targetSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(targetType));
|
||||
const callbacks = sourceSig && targetSig && !sourceSig.typePredicate && !targetSig.typePredicate &&
|
||||
(getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable);
|
||||
const related = callbacks ?
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
tests/cases/compiler/mutuallyRecursiveCallbacks.ts(7,1): error TS2322: Type '<T>(bar: Bar<T>) => void' is not assignable to type 'Bar<{}>'.
|
||||
Types of parameters 'bar' and 'foo' are incompatible.
|
||||
Types of parameters 'bar' and 'foo' are incompatible.
|
||||
Type 'Foo<{}>' is not assignable to type 'Bar<{}>'.
|
||||
Types of parameters 'bar' and 'foo' are incompatible.
|
||||
Type 'void' is not assignable to type 'Foo<{}>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/mutuallyRecursiveCallbacks.ts (1 errors) ====
|
||||
// Repro from #18277
|
||||
|
||||
interface Foo<T> { (bar: Bar<T>): void };
|
||||
type Bar<T> = (foo: Foo<T>) => Foo<T>;
|
||||
declare function foo<T>(bar: Bar<T>): void;
|
||||
declare var bar: Bar<{}>;
|
||||
bar = foo;
|
||||
~~~
|
||||
!!! error TS2322: Type '<T>(bar: Bar<T>) => void' is not assignable to type 'Bar<{}>'.
|
||||
!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible.
|
||||
!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'Foo<{}>' is not assignable to type 'Bar<{}>'.
|
||||
!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'void' is not assignable to type 'Foo<{}>'.
|
||||
|
||||
14
tests/baselines/reference/mutuallyRecursiveCallbacks.js
Normal file
14
tests/baselines/reference/mutuallyRecursiveCallbacks.js
Normal file
@ -0,0 +1,14 @@
|
||||
//// [mutuallyRecursiveCallbacks.ts]
|
||||
// Repro from #18277
|
||||
|
||||
interface Foo<T> { (bar: Bar<T>): void };
|
||||
type Bar<T> = (foo: Foo<T>) => Foo<T>;
|
||||
declare function foo<T>(bar: Bar<T>): void;
|
||||
declare var bar: Bar<{}>;
|
||||
bar = foo;
|
||||
|
||||
|
||||
//// [mutuallyRecursiveCallbacks.js]
|
||||
// Repro from #18277
|
||||
;
|
||||
bar = foo;
|
||||
34
tests/baselines/reference/mutuallyRecursiveCallbacks.symbols
Normal file
34
tests/baselines/reference/mutuallyRecursiveCallbacks.symbols
Normal file
@ -0,0 +1,34 @@
|
||||
=== tests/cases/compiler/mutuallyRecursiveCallbacks.ts ===
|
||||
// Repro from #18277
|
||||
|
||||
interface Foo<T> { (bar: Bar<T>): void };
|
||||
>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 2, 14))
|
||||
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 20))
|
||||
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
|
||||
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 2, 14))
|
||||
|
||||
type Bar<T> = (foo: Foo<T>) => Foo<T>;
|
||||
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
|
||||
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9))
|
||||
>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 15))
|
||||
>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9))
|
||||
>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9))
|
||||
|
||||
declare function foo<T>(bar: Bar<T>): void;
|
||||
>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 38))
|
||||
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 4, 21))
|
||||
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 4, 24))
|
||||
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
|
||||
>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 4, 21))
|
||||
|
||||
declare var bar: Bar<{}>;
|
||||
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 5, 11))
|
||||
>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41))
|
||||
|
||||
bar = foo;
|
||||
>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 5, 11))
|
||||
>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 38))
|
||||
|
||||
35
tests/baselines/reference/mutuallyRecursiveCallbacks.types
Normal file
35
tests/baselines/reference/mutuallyRecursiveCallbacks.types
Normal file
@ -0,0 +1,35 @@
|
||||
=== tests/cases/compiler/mutuallyRecursiveCallbacks.ts ===
|
||||
// Repro from #18277
|
||||
|
||||
interface Foo<T> { (bar: Bar<T>): void };
|
||||
>Foo : Foo<T>
|
||||
>T : T
|
||||
>bar : Bar<T>
|
||||
>Bar : Bar<T>
|
||||
>T : T
|
||||
|
||||
type Bar<T> = (foo: Foo<T>) => Foo<T>;
|
||||
>Bar : Bar<T>
|
||||
>T : T
|
||||
>foo : Foo<T>
|
||||
>Foo : Foo<T>
|
||||
>T : T
|
||||
>Foo : Foo<T>
|
||||
>T : T
|
||||
|
||||
declare function foo<T>(bar: Bar<T>): void;
|
||||
>foo : <T>(bar: Bar<T>) => void
|
||||
>T : T
|
||||
>bar : Bar<T>
|
||||
>Bar : Bar<T>
|
||||
>T : T
|
||||
|
||||
declare var bar: Bar<{}>;
|
||||
>bar : Bar<{}>
|
||||
>Bar : Bar<T>
|
||||
|
||||
bar = foo;
|
||||
>bar = foo : <T>(bar: Bar<T>) => void
|
||||
>bar : Bar<{}>
|
||||
>foo : <T>(bar: Bar<T>) => void
|
||||
|
||||
7
tests/cases/compiler/mutuallyRecursiveCallbacks.ts
Normal file
7
tests/cases/compiler/mutuallyRecursiveCallbacks.ts
Normal file
@ -0,0 +1,7 @@
|
||||
// Repro from #18277
|
||||
|
||||
interface Foo<T> { (bar: Bar<T>): void };
|
||||
type Bar<T> = (foo: Foo<T>) => Foo<T>;
|
||||
declare function foo<T>(bar: Bar<T>): void;
|
||||
declare var bar: Bar<{}>;
|
||||
bar = foo;
|
||||
Loading…
x
Reference in New Issue
Block a user