#Typing for state.matches
1 messages · Page 1 of 1 (latest)
Not currently possible in v4, unless you're using typegen and want to do some funky typings (let me know if you do)
We are using typegen, depends how funky the typing is 
You can use something like typeof state['matches'] - if you have the machine, that's typeof machine['initialState']['matches'] or something like that. You can grab the type of the first arg
That seems to satisfy the type on the matches(stateMatch), but is throwing the following type error when trying to pass in a string to match against:
import {AnyStateMachine, StateFrom} from 'xstate';
/**
* Generates a strongly typed selector for determining if a xstate machine
* is currently in the specified state.
* @param stateMatcher the string or object to match
* @returns the xstate selector
*/
export function generateSelector<T extends AnyStateMachine>(
stateMatcher: T['initialState']['matches']
) {
return (state: StateFrom<T>) => state.matches(stateMatcher);
}
import {trackMachine} from "../machines/trackMachine";
export type TrackMachine = typeof trackMachine;
export const useIsOpen = (service: TrackService): boolean => {
return useSelector(service, generateSelector<TrackMachine>('open'));
};
☝️ The open gives this error:
Argument of type 'string' is not assignable to parameter of type '{ <TSV extends "closed" | "open" | "pendingClose">(parentStateValue: TSV): boolean; <TSV extends never>(parentStateValue: TSV): this is State<TrackContext, { type: "openPanel"; } | { type: "closePanel"; } | ... 4 more ... | { ...; }, any, { ...; }, ResolveTypegenMeta<...>> & { ...; }; }'.ts(2345)
I'm impressed that you got it working that far... anyway, with TS I think you need to do 'open' as const or something like that
as const gives the same error unfortunately. In the typegen file there's matchesStates which is a union of the strings I'd expect. Is there a way to get that value from the typeof TrackMachine or similar? (I'm not familiar with how Typegen works under the hood so I'm not sure)
Not sure off the top of my head (cc. @brisk geode if you may know the answer)
If it's any consolation, in v5 it will be possible to have a strongly-typed state value: https://github.com/statelyai/xstate/pull/3940
Parameters<StateFrom<typeof machine>['matches']>[0]
if u want to grab the type accepted by matches
perhaps I misunderstood the question though
That is what I'm trying to do, yes. That's giving me never though. This is what I have in StateFrom<TrackMachine>['matches']
But TSV is never when attempting to pull it out of the tuple
type StateValuesFrom<T extends AnyStateMachine> = StateFrom<T>['matches'] extends {
(value: infer StateValues): any
(value: any): any
} ? StateValues : never
smth along those lines should work
unfortunately, conditional types in TS only grab the last overload
and this one is first, so we have to match against 2 call signatures, to infer from the first one