From f49eb94d590f54dddb66215370c92eb0f4a8de68 Mon Sep 17 00:00:00 2001 From: Syth-1 Date: Sat, 22 Feb 2025 18:10:50 +0000 Subject: [PATCH 1/3] Update stronger typehint when building state machine ('initial' & 'on') --- packages/core/src/createMachine.ts | 18 +++++-- packages/core/src/types.ts | 77 +++++++++++++++++++++++------- 2 files changed, 74 insertions(+), 21 deletions(-) diff --git a/packages/core/src/createMachine.ts b/packages/core/src/createMachine.ts index cacd45ff5f..c96d30088b 100644 --- a/packages/core/src/createMachine.ts +++ b/packages/core/src/createMachine.ts @@ -1,5 +1,10 @@ import { StateMachine } from './StateMachine.ts'; -import { ResolvedStateMachineTypes, TODO } from './types.ts'; +import { + ResolvedStateMachineTypes, + StatesConfig, + StrictType, + TODO +} from './types.ts'; import { AnyActorRef, EventObject, @@ -84,6 +89,8 @@ export function createMachine< TOutput extends NonReducibleUnknown, TEmitted extends EventObject, TMeta extends MetaObject, + TStates extends Record, + TStrictType extends StrictType, // it's important to have at least one default type parameter here // it allows us to benefit from contextual type instantiation as it makes us to pass the hasInferenceCandidatesOrDefault check in the compiler // we should be able to remove this when we start inferring TConfig, with it we'll always have an inference candidate @@ -115,8 +122,13 @@ export function createMachine< TInput, TOutput, TEmitted, - TMeta - >, + TMeta, + TStates, + Extract, + TStrictType + > & { + strictType?: TStrictType; + }, implementations?: InternalMachineImplementations< ResolvedStateMachineTypes< TContext, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 540a34b748..ae29a85cef 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -306,7 +306,7 @@ export interface StateValueMap { */ export type StateValue = string | StateValueMap; -export type TransitionTarget = SingleOrArray; +export type TransitionTarget = SingleOrArray; export interface TransitionConfig< TContext extends MachineContext, @@ -317,7 +317,9 @@ export interface TransitionConfig< TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject = EventObject, - TMeta extends MetaObject = MetaObject + TMeta extends MetaObject = MetaObject, + TParent extends string = string, + TStrictType extends StrictType = undefined > { guard?: Guard; actions?: Actions< @@ -332,7 +334,7 @@ export interface TransitionConfig< TEmitted >; reenter?: boolean; - target?: TransitionTarget | undefined; + target?: TransitionTarget> | undefined; meta?: TMeta; description?: string; } @@ -513,9 +515,11 @@ export type StatesConfig< TTag extends string, TOutput, TEmitted extends EventObject, - TMeta extends MetaObject + TMeta extends MetaObject, + TStates extends Record = Record, + TStrictType extends StrictType = undefined > = { - [K in string]: StateNodeConfig< + [K in keyof TStates]: StateNodeConfig< TContext, TEvent, TActor, @@ -525,7 +529,10 @@ export type StatesConfig< TTag, TOutput, TEmitted, - TMeta + TMeta, + TStates[K], + Extract, + TStrictType >; }; @@ -536,7 +543,7 @@ export type StatesDefinition< [K in string]: StateNodeDefinition; }; -export type TransitionConfigTarget = string | undefined; +export type TransitionConfigTarget = T | undefined; export type TransitionConfigOrTarget< TContext extends MachineContext, @@ -547,9 +554,11 @@ export type TransitionConfigOrTarget< TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject, - TMeta extends MetaObject + TMeta extends MetaObject, + TParent extends string = string, + TStrictType extends StrictType = undefined > = SingleOrArray< - | TransitionConfigTarget + | TransitionConfigTarget> | TransitionConfig< TContext, TExpressionEvent, @@ -559,7 +568,9 @@ export type TransitionConfigOrTarget< TGuard, TDelay, TEmitted, - TMeta + TMeta, + TParent, + TStrictType > >; @@ -571,7 +582,9 @@ export type TransitionsConfig< TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject, - TMeta extends MetaObject + TMeta extends MetaObject, + TParent extends string = string, + TStrictType extends StrictType = undefined > = { [K in EventDescriptor]?: TransitionConfigOrTarget< TContext, @@ -582,7 +595,9 @@ export type TransitionsConfig< TGuard, TDelay, TEmitted, - TMeta + TMeta, + TParent, + TStrictType >; }; @@ -864,12 +879,16 @@ export interface StateNodeConfig< TTag extends string, _TOutput, TEmitted extends EventObject, - TMeta extends MetaObject + TMeta extends MetaObject, + TStates extends Record = Record, + TParent extends string = string, + TStrictType extends StrictType = undefined > { /** The initial state transition. */ + initial?: | InitialTransitionConfig - | string + | StrictSelect>, TStrictType> | undefined; /** * The type of this state node: @@ -901,7 +920,9 @@ export interface StateNodeConfig< TTag, NonReducibleUnknown, TEmitted, - TMeta + TMeta, + TStates, + TStrictType > | undefined; /** @@ -929,7 +950,9 @@ export interface StateNodeConfig< TGuard, TDelay, TEmitted, - TMeta + TMeta, + TParent, + TStrictType >; /** The action(s) to be executed upon entering the state node. */ entry?: Actions< @@ -1351,7 +1374,10 @@ export type MachineConfig< TInput = any, TOutput = unknown, TEmitted extends EventObject = EventObject, - TMeta extends MetaObject = MetaObject + TMeta extends MetaObject = MetaObject, + TStates extends Record = Record, + TParent extends string = string, + TStrictType extends StrictType = undefined > = (Omit< StateNodeConfig< DoNotInfer, @@ -1363,13 +1389,17 @@ export type MachineConfig< DoNotInfer, DoNotInfer, DoNotInfer, - DoNotInfer + DoNotInfer, + TStates, + TParent, + TStrictType >, 'output' > & { /** The initial context (extended state) */ /** The machine's own version. */ version?: string; + // TODO: make it conditionally required output?: Mapper | TOutput; }) & @@ -2678,3 +2708,14 @@ export type BuiltinActionResolution = [ NonReducibleUnknown, // params UnknownAction[] | undefined ]; + +export type StrictType = 'strict' | 'loose' | undefined; + +type StrictSelect< + elements extends string, + strict extends StrictType = undefined +> = strict extends 'strict' + ? elements + : strict extends 'loose' + ? elements | (string & {}) + : string; From ec30278e5f9ca12b0765950da33e0980bfecaa9d Mon Sep 17 00:00:00 2001 From: Syth-1 Date: Tue, 4 Mar 2025 14:21:57 +0000 Subject: [PATCH 2/3] Added changeset --- .changeset/many-tips-sit.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/many-tips-sit.md diff --git a/.changeset/many-tips-sit.md b/.changeset/many-tips-sit.md new file mode 100644 index 0000000000..4433044d0a --- /dev/null +++ b/.changeset/many-tips-sit.md @@ -0,0 +1,5 @@ +--- +'xstate': minor +--- + +Added a new flag 'scriptType' to state machine which provides different levels of typehint for states 'initial' and 'on' properties. From 16d17da997af6feff1904768ef557f3ec1dd00bb Mon Sep 17 00:00:00 2001 From: Syth-1 Date: Wed, 5 Mar 2025 15:43:13 +0000 Subject: [PATCH 3/3] Removed unrequired import --- packages/core/src/createMachine.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/core/src/createMachine.ts b/packages/core/src/createMachine.ts index c96d30088b..1b4463a8ab 100644 --- a/packages/core/src/createMachine.ts +++ b/packages/core/src/createMachine.ts @@ -1,10 +1,5 @@ import { StateMachine } from './StateMachine.ts'; -import { - ResolvedStateMachineTypes, - StatesConfig, - StrictType, - TODO -} from './types.ts'; +import { ResolvedStateMachineTypes, StrictType, TODO } from './types.ts'; import { AnyActorRef, EventObject,