diff --git a/.changeset/nervous-chicken-eat.md b/.changeset/nervous-chicken-eat.md new file mode 100644 index 0000000000..97f36c0655 --- /dev/null +++ b/.changeset/nervous-chicken-eat.md @@ -0,0 +1,5 @@ +--- +'xstate': patch +--- + +Actors with emitted events should no longer cause type issues: https://github.com/statelyai/xstate/issues/4931 diff --git a/packages/core/src/actors/index.ts b/packages/core/src/actors/index.ts index d0a28956bd..1bad525665 100644 --- a/packages/core/src/actors/index.ts +++ b/packages/core/src/actors/index.ts @@ -27,6 +27,7 @@ const emptyLogic = fromTransition((_) => undefined, undefined); export function createEmptyActor(): ActorRef< Snapshot, + AnyEventObject, AnyEventObject > { return createActor(emptyLogic); diff --git a/packages/core/src/createActor.ts b/packages/core/src/createActor.ts index 5aca1a6263..f7d149359a 100644 --- a/packages/core/src/createActor.ts +++ b/packages/core/src/createActor.ts @@ -71,7 +71,8 @@ const defaultOptions = { * An Actor is a running process that can receive events, send events and change its behavior based on the events it receives, which can cause effects outside of the actor. When you run a state machine, it becomes an actor. */ export class Actor - implements ActorRef, EventFromLogic> + implements + ActorRef, EventFromLogic, EmittedFrom> { /** * The current internal state of the actor. @@ -106,7 +107,11 @@ export class Actor public _parent?: AnyActorRef; /** @internal */ public _syncSnapshot?: boolean; - public ref: ActorRef, EventFromLogic>; + public ref: ActorRef< + SnapshotFrom, + EventFromLogic, + EmittedFrom + >; // TODO: add typings for system private _actorScope: ActorScope< SnapshotFrom, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 8675e56706..ac13c45f59 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -121,7 +121,8 @@ export interface UnifiedArg< unknown, TODO // TMeta >, - TEvent + TEvent, + AnyEventObject >; system: AnyActorSystem; } @@ -169,7 +170,7 @@ export type OutputFrom = T extends ActorLogic< infer _TEmitted > ? (TSnapshot & { status: 'done' })['output'] - : T extends ActorRef + : T extends ActorRef ? (TSnapshot & { status: 'done' })['output'] : never; @@ -1521,7 +1522,8 @@ export type ContextFactory< unknown, TODO // TMeta >, - TEvent + TEvent, + AnyEventObject >; }) => TContext; @@ -1827,7 +1829,8 @@ export type Mapper< unknown, TODO // TMeta >, - TEvent + TEvent, + AnyEventObject >; }) => TResult; @@ -2181,7 +2184,7 @@ export interface ActorRef< ) => Subscription; } -export type AnyActorRef = ActorRef; +export type AnyActorRef = ActorRef; export type ActorLogicFrom = ReturnTypeOrValue extends infer R ? R extends StateMachine< @@ -2232,7 +2235,8 @@ export type ActorRefFrom = ReturnTypeOrValue extends infer R TOutput, TMeta >, - TEvent + TEvent, + TEmitted > : R extends Promise ? ActorRefFrom> @@ -2243,7 +2247,7 @@ export type ActorRefFrom = ReturnTypeOrValue extends infer R infer _TSystem, infer TEmitted > - ? ActorRef + ? ActorRef : never : never; @@ -2341,7 +2345,7 @@ export interface ActorScope< TSystem extends AnyActorSystem = AnyActorSystem, TEmitted extends EventObject = EventObject > { - self: ActorRef; + self: ActorRef; id: string; sessionId: string; logger: (...args: any[]) => void; @@ -2469,7 +2473,7 @@ export type UnknownActorLogic = ActorLogic< >; export type SnapshotFrom = ReturnTypeOrValue extends infer R - ? R extends ActorRef + ? R extends ActorRef ? TSnapshot : R extends Actor ? SnapshotFrom @@ -2541,7 +2545,7 @@ type ResolveEventType = ReturnTypeOrValue extends infer R infer _TMeta > ? TEvent - : R extends ActorRef + : R extends ActorRef ? TEvent : never : never; diff --git a/packages/core/test/types.test.ts b/packages/core/test/types.test.ts index 225c7dd274..bcab8cc604 100644 --- a/packages/core/test/types.test.ts +++ b/packages/core/test/types.test.ts @@ -18,7 +18,8 @@ import { sendTo, spawnChild, stateIn, - setup + setup, + toPromise } from '../src/index'; function noop(_x: unknown) { @@ -4553,3 +4554,16 @@ describe('snapshot methods', () => { snapshot.toJSON(); }); }); + +// https://github.com/statelyai/xstate/issues/4931 +it('fromPromise should not have issues with actors with emitted types', () => { + const machine = setup({ + types: { + emitted: {} as { type: 'FOO' } + } + }).createMachine({}); + + const actor = createActor(machine).start(); + + toPromise(actor); +}); diff --git a/packages/xstate-solid/src/fromActorRef.ts b/packages/xstate-solid/src/fromActorRef.ts index abc1e1d7d5..9787a0569f 100644 --- a/packages/xstate-solid/src/fromActorRef.ts +++ b/packages/xstate-solid/src/fromActorRef.ts @@ -1,10 +1,10 @@ import { Accessor, createEffect, createMemo, onCleanup } from 'solid-js'; -import { ActorRef, SnapshotFrom } from 'xstate'; +import { AnyActorRef, SnapshotFrom } from 'xstate'; import { createImmutable } from './createImmutable.ts'; const noop = () => {}; -export function fromActorRef | undefined>( +export function fromActorRef( actorRef: Accessor | TActor ): Accessor< | SnapshotFrom>