Skip to content

Instantiate conditional types when providing conditional types #48823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

Andarist
Copy link
Contributor

Fixes #46310

The problem was that in this case there are no inference candidates AND logic is somewhat sensitive to where you put a conditional type in your declaration, see the diff that "magically" make it works:

diff --git a/repro_case.ts b/repro_case.ts
index 7a3795816..f9a7f1918 100644
--- a/repro_case.ts
+++ b/repro_case.ts
@@ -14,9 +14,9 @@ declare function createMachine<
   config: {
     types?: TTypesMeta;
   },
-  implementations: TTypesMeta extends TypegenEnabled
-    ? ActionFunction<{ type: 'test' }>
-    : ActionFunction<{ type: string }>
+  implementations: ActionFunction<
+    TTypesMeta extends TypegenEnabled ? { type: 'test' } : { type: string }
+  >
 ): void;

So why the repro case doesn't work and why this workaround works? The problem is that within getApparentTypeOfContextualType the call to instantiateContextualType doesn't touch this conditional type anyhow (again, cause there are no inference candidates gathered before hand) but the mapType(instantiatedType, getApparentType, /*noReductions*/ true); calls getBaseConstraintOfType(type) and that is returning union like this:

ActionFunction<{ type: "test"; }> | ActionFunction<{ type: string; }>

So the function becomes non-inferrable from that in the same way as in here:

declare function call(fn: ((a: string) => void) | ((a: 'test') => void)): void

call((a) => {
  // oops, implicit any
})

When we use a workaround (moving conditional type further down the road):

ActionFunction<
    TTypesMeta extends TypegenEnabled ? { type: 'test' } : { type: string }
>

Then it becomes:

(ev: TTypesMeta extends TypegenEnabled ? { type: 'test' } : { type: string }) => void

It's a single signature, it's returned fine from getContextualSignature and then contextuallyCheckFunctionExpressionOrObjectLiteralMethod is able to infer from it using inferFromAnnotatedParameters+instantiateSignature (and thus resolve this default param, even though there is no candidate for it)

# Conflicts:
#	src/compiler/checker.ts
@Andarist
Copy link
Contributor Author

this gets superseded by #50994

@Andarist Andarist closed this Sep 29, 2022
@Andarist Andarist deleted the fix/46310 branch September 29, 2022 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Milestone Bug PRs that fix a bug with a specific milestone
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Type of a function argument not inferred from context when defined using conditional type
3 participants