microsoft / microsoft/TypeScript
Type inference of generics does not work only when callback takes argument
Personne n'a encore pris cette issue.
- Langage dominant
- Go
- Étoiles
- 111k
- Forks
- 14.3k
- Merge moyen
- 2 j 4 h
- PR mergées (30 j)
- 132
Description
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.
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par l’exemple repro.ts et tsconfig.json, puis exécutez npx tsc avec strictFunctionTypes activé pour confirmer l’échec de l’inférence. Suivez la manière dont les types de retour génériques sont inférés lorsque P1 et P2 sont utilisés comme une intersection, et vérifiez la complétion lorsque le callback prend un argument, sans modifier les types inférés attendus.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- typescript
- Domaine
- compilers
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Clairement spécifiée
- Accessibilité débutants
- 35/100