microsoft / microsoft/TypeScript
Type inference of generics does not work only when callback takes argument
Nessuno ha ancora preso questa issue.
- Lingua principale
- Go
- Stelle
- 111k
- Fork
- 14.3k
- Merge medio
- 2g 4h
- PR unite (30g)
- 132
Descrizione
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.
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con l’esempio repro.ts e tsconfig.json, quindi esegui npx tsc con strictFunctionTypes abilitato per confermare il fallimento dell’inferenza. Traccia il modo in cui vengono inferiti i tipi restituiti generici quando P1 e P2 vengono usati come un’intersezione, e verifica il completamento quando il callback accetta un argomento senza modificare i tipi inferiti previsti.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- typescript
- Ambito
- compilers
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 35/100