-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Nested call not inferred correctly when a conditional type tries to route to the final expected type #46201
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
Comments
I think a more minimal repro would help, if you can come up with one. |
@andrewbranch I've managed to slim down the repro further (added to the original post). Interestingly, I've also been able to create a semantically equivalent variant that works (in my real code it's way harder to apply the same technique though). The difference between both might be an outcome of some implementation decision but for me, a user, it's hard to assess that and it's also hard to know how I can work around issues like this when they pop up. If you have any pointers as to why this happens, or how this possibly could be fixed in the TS compiler then I could try to work on that said fix (if it would not be too involved, ofc). I've spent my fair share of time in the debugger with |
@millsp has found out that wrapping this conditional type in diff --git a/repro_case.ts b/repro_case.ts
index 37eb31f9e..c78f843e7 100644
--- a/repro_case.ts
+++ b/repro_case.ts
@@ -20,15 +20,19 @@ declare function assign<TEvent extends EventObject>(
assignment: (ev: TEvent) => void
): ActionObject<TEvent>;
+type NoOp<T> = { [K in keyof T]: T[K] };
+
declare function createMachine<
TTypesMeta extends TypegenConstraint = TypegenDisabled
>(
config: {
types?: TTypesMeta;
},
- action?: TTypesMeta extends TypegenEnabled
- ? { action: ActionObject<{ type: 'WITH_TYPEGEN' }> }
- : { action: ActionObject<{ type: 'WITHOUT_TYPEGEN' }> }
+ action?: NoOp<
+ TTypesMeta extends TypegenEnabled
+ ? { action: ActionObject<{ type: 'WITH_TYPEGEN' }> }
+ : { action: ActionObject<{ type: 'WITHOUT_TYPEGEN' }> }
+ >
): void;
createMachine( |
I've found yet another workaround for this particular issue (the slimmed-down repro) - it doesn't help me in my project though as it breaks some other stuff: diff --git a/repro_case.ts b/repro_case.ts
index 0ee0107..1e4fd8b 100644
--- a/repro_case.ts
+++ b/repro_case.ts
@@ -9,11 +9,12 @@ type ActionFunction<TEvent extends { type: string }> = (event: TEvent) => void;
// this is supposed to "route" the second argument based on the information provided within the first one
declare function createMachine<
- TTypesMeta extends TypegenEnabled | TypegenDisabled = TypegenDisabled
->(
- config: {
+ TTypesMeta extends TypegenEnabled | TypegenDisabled = TypegenDisabled,
+ TConfig = {
types?: TTypesMeta;
- },
+ }
+>(
+ config: TConfig,
implementations: TTypesMeta extends TypegenEnabled
? ActionFunction<{ type: "test" }>
: ActionFunction<{ type: string }> Basically what I would like is to make TS:
The problem is that I have some nested generic calls expressions in the second argument and if I apply this workaround then they infer based on both branches of this conditional type. I would like to completely prevent it - TS should only start looking into the second argument while having the rest already computed. |
I havenβt fully wrapped my head around this issue, but it sounds like youβre saying this would help? #14829 |
I think that this would have the potential to fix this if it would be baked into the language. We are already using I've tried to apply I'm basically on the lookout here for a trick to make TS start processing the second argument only after it settles the first one but I've already thrown all the tricks I got at this and I can't make it work. I've briefly thought that forcing the resolution with |
Bug Report
π Search Terms
inference, type parameters, conditional type, signature resolving
π Version & Regression Information
This is the behavior present in all 4.x versions available on the playground, including 4.5-beta.
β― Playground Link
Slimmed down repro case
The originally reported TS playground
π» Code
This is the code for the slimmed-down variant. Note that the
createMachine2
is not a part of the repro case but it shows how putting the conditional type on a "different level" makes it work - which I find to be surprising because semantically both variants do the same thingThe code below showcases more accurately what I'm trying to achieve.
Code from the originally reported playground
π Actual behavior
event
parameter here is not narrowed down to the WITH_TYPEGEN event, yet theactionName
's type (available when I hover over the property) is "correct" (only WITH_TYPEGEN event there)π Expected behavior
I would expect this
event
parameter to be inferred correctly.I've been debugging this for a bit and I think this is roughly what happens:
chooseOverload
+inferTypeArguments
calls becauseassign
happens "within"createMachine
typeParameters
forassign
are assigned based on both branches of the conditional type - basically, a union of both is created for this position and since there is an overlap the reduced type gets assigned there.inferTypeArguments
and it happens withingetSignatureApplicabilityError
but theassign
has been instantiated and cached a step back - withininferTypeArguments
assign
is never rechecked - so it stays as if it was supposed to handle both branches of the conditional typeNote that this might be highly incorrect as I'm not too familiar with the codebase
The text was updated successfully, but these errors were encountered: