microsoft / microsoft/TypeScript

Type inference of generics does not work only when callback takes argument

Offen
#29,123 3 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bug Domain: check: Type Inference
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:

  • strictFunctionTypes
  • argument intersection type
  • generic argument
  • generic 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

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Ö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

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.