Inferences made when trying to match an overload are carried over to matching consecutive overloads
See original GitHub issueBug Report
š Search Terms
overload inference generic consecutive subsequent following
the only issue that I have found that might be related to this is this one but I canāt assess on my own if they are the same or not
š Version & Regression Information
This is the behavior present in all 4.x versions available on the playground, including 4.5-beta.
āÆ Playground Link
Playground link with relevant code
š» Code
interface TypegenDisabled {
"@@xstate/typegen": false;
}
interface TypegenEnabled {
"@@xstate/typegen": true;
}
interface EventObject {
type: string;
}
interface ActionObject<TEvent extends EventObject> {
_TE: TEvent;
}
interface StateMachine<
TEvent extends EventObject,
TTypesMeta = TypegenDisabled
> {
_TE: TEvent;
_TRTM: TTypesMeta;
}
interface MachineOptions<TEvent extends EventObject> {
action?: ActionObject<TEvent>;
}
type MaybeTypegenMachineOptions<
TEvent extends EventObject,
TTypesMeta = TypegenDisabled
> = TTypesMeta extends TypegenEnabled
? {
action?: ActionObject<{ type: "WITH_TYPEGEN" }>;
}
: MachineOptions<TEvent>;
declare function assign<TEvent extends EventObject>(
assignment: (ev: TEvent) => void
): ActionObject<TEvent>;
// atm I have a single signature and it **matches**
// however, if I uncomment this additional overload then **no signature** matches
// if later on I reorder the signatures then the first one (the one that is currently not commented out) matches
// what happens here is that some inferences made when attempting to match the first overload are cached
// and "carried over" to matching the second overload - which makes the whole thing fail
// declare function useMachine<
// TEvent extends EventObject,
// TTypesMeta extends TypegenEnabled
// >(
// getMachine: StateMachine<TEvent, TTypesMeta>,
// options: MaybeTypegenMachineOptions<TEvent, TTypesMeta>
// ): { first: true };
declare function useMachine<TEvent extends EventObject>(
getMachine: StateMachine<TEvent>,
options?: MachineOptions<TEvent>
): { second: true };
const machine = {} as StateMachine<{ type: "WITHOUT_TYPEGEN" }>;
const ret = useMachine(machine, {
action: assign((_ev) => {
((_type: "WITHOUT_TYPEGEN") => null)(_ev.type);
}),
});
š Actual behavior
No overload signature matches
š Expected behavior
I would expect a signature to match when itās used as one of the overloads if it matches on its own. And I would expect for inferences made in a failed attempt to match a signature to have no effect on matching the following signatures.
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (10 by maintainers)
Top Results From Across the Web
Need a dummy overload to improve inference Ā· Issue #39850 ...
Andarist mentioned this issue on Oct 11, 2021. Inferences made when trying to match an overload are carried over to matching consecutive overloads...
Read more >Issues Ā· microsoft/TypeScript Ā· GitHub
Inferences made when trying to match an overload are carried over to matching consecutive overloads Bug A bug in TypeScript Needs Investigation This...
Read more >Creating Mock Classes
To disambiguate functions overloaded on the const-ness of this object, use the Const() argument wrapper. using ::testing::ReturnRef; class MockFoo : public FooĀ ...
Read more >Overload and Overcurrent Protection ā Basic Motor Control
It is caused by excessive amounts of current drawn by a motor, which may be as high as six times the rated current....
Read more >gMock Cookbook | GoogleTest
When a mock method is called, the last matching expectation that's still active will be selected (think ānewer overrides olderā). So, you can...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@AlCalzone I donāt believe those are the same. Iāve created even more simplified demo of your issue:
Playground link
The problem here is that each overload is type-checked separately and your argument that is a union doesnāt satisfy any of those overloads on its own. TypeScript doesnāt try to match this argument against all of the overloads at once.
As to my problemā¦ Iāve spent a significant amount of time investigating this in the debugger. And the root reason behind this issue is quite mundane - itās caching (at least to some extent).
The problem is that we are dealing with some nested calls here and while trying to choose the first overload the inferences are made for the inner
assign
call. The first overload doesnāt match but the inference made toassign
persists in its.resolvedType
(or a similar) - and when we get to matching the second overload this type is just being reused, causing this type error. If we could only smartly discard the cached value then it would ājust workā. Iāve even managed to bypass this prtical cache (conditionally), just as an experiment, but Iāve then hit another layer of caching elsewhere and I gave up.The actual error is here: https://github.com/unional/events-plus/blob/fsa-error/ts/supportFSA.spec.ts#L43
The type of
event
isconst event: FSAEventBare<string> | FSAEventWithErrorPayload<string, Error>
.You can see that calling with no param is fine as in https://github.com/unional/events-plus/blob/fsa-error/ts/supportFSA.spec.ts#L32
because I have declare a the signature of
() => FSA<...>
on both interfaces.But the return type of
event({ error: true })
is wrong (it gets the return typeFSA<...>
, the return type of() => ...
, instead ofErrorFSABare<>
)You can see the error directly in sandbox
Iām trying to reduce that to a simpler example.