microsoft / microsoft/TypeScript
Type inference of generics does not work only when callback takes argument
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Go
- Sterne
- 111k
- Forks
- 14.3k
- Ø Merge
- 1 T. 19 Std.
- Gemergte PRs (30 T.)
- 117
Beschreibung
I encountered a strange behavior of type inference about the generic arguments and intersection type. The error described below occurs only when the strictFunctionTypes option is enabled.
TypeScript Version:
Version 3.3.0-dev.20181221
Search Terms:
strictFunctionTypesargument intersection typegeneric argumentgeneric intersection type
Code
tsconfig.json:
{
"compilerOptions": {
"moduleResolution": "node",
"target": "es6",
"module":"commonjs",
"strictFunctionTypes": true,
"outDir": "dist"
},
"include": ["*.ts"]
}
source:
const run = <P1, P2>(
makeProps1: (s: string) => P1,
makeProps2: () => P2,
useBoth: (props: P1 & P2) => void
) => {};
const foo = (props: { n: number; b: boolean }) => {};
// This works as expected.
run(() => ({ n: 1 }), () => ({ b: true }), foo);
// But if the first argument function takes a parameter `s`, it results in a compile error.
run(s => ({ n: 1 }), () => ({ b: true }), foo);
Expected behavior:
The type of run is inferred correctly from run(s => ({ n: 1 }), () => ({ b: true }), foo) as below and the code compiles.
const run: <{ n: number; }, { b: boolean; }>(makeProps1: (s: string) => { n: number; }, makeProps2: () => { b: boolean; }, useBoth: (props: { n: number; } & { b: boolean; }) => void) => void
This type is generated from run(() => ({ n: 1 }), () => ({ b: true }), foo). I copied it from Playground's tooltip.
Actual behavior:
It results in the compile error.
output of npx tsc:
repro.ts:9:43 - error TS2345: Argument of type '(props: { n: number; b: boolean; }) => void' is not assignable to parameter of type '(props: { b: boolean; }) => void'.
Types of parameters 'props' and 'props' are incompatible.
Property 'n' is missing in type '{ b: boolean; }' but required in type '{ n: number; b: boolean; }'.
9 run(s => ({ n: 1 }), () => ({ b: true }), foo);
~~~
repro.ts:7:23
7 const foo = (props: { n: number; b: boolean }) => {};
~
'n' is declared here.
Found 1 error.
This is because the return type of makeProps1 is inferred as {} instead of { n: number; }.
const run: <{}, { b: boolean; }>(makeProps1: (s: string) => {}, makeProps2: () => { b: boolean; }, useBoth: (props: { b: boolean; }) => void) => void
Playground Link:
Here. Note that this problem occurs only when the strictFunctionTypes option is enabled.
Related Issues:
I could not find.
Other Investigation:
In the code below, the type inference works as expected:
const run2 = <P1, P2>(
makeProps1: (s: string) => P1,
makeProps2: () => P2,
useProps1: (p: P1) => void,
useProps2: (p: P2) => void
) => {};
// The first argument function takes a parameter `s` but it does not change the type inference behavior.
run2(
s => ({ n: 1 }),
() => ({ b: true }),
(p1: { n: number }) => {},
(p2: { b: boolean }) => {}
);
So it seems that the error only occurs when the generic types (P1, P2) are used as intersection type.
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit dem Beispiel repro.ts und tsconfig.json und führe dann npx tsc mit aktiviertem strictFunctionTypes aus, um den Fehler bei der Inferenz zu bestätigen. Verfolge, wie die generischen Rückgabetypen inferiert werden, wenn P1 und P2 als Schnittmenge verwendet werden, und überprüfe die Vervollständigung, wenn der Callback ein Argument entgegennimmt, ohne die erwarteten inferierten Typen zu ändern.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- typescript
- Bereich
- compilers
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 35/100