Skip to content
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

[core] Fix type issues with emitted events #4932

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nervous-chicken-eat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': patch
---

Actors with emitted events should no longer cause type issues: https://github.com/statelyai/xstate/issues/4931
1 change: 1 addition & 0 deletions packages/core/src/actors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const emptyLogic = fromTransition((_) => undefined, undefined);

export function createEmptyActor(): ActorRef<
Snapshot<undefined>,
AnyEventObject,
AnyEventObject
> {
return createActor(emptyLogic);
Expand Down
9 changes: 7 additions & 2 deletions packages/core/src/createActor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<TLogic extends AnyActorLogic>
implements ActorRef<SnapshotFrom<TLogic>, EventFromLogic<TLogic>>
implements
ActorRef<SnapshotFrom<TLogic>, EventFromLogic<TLogic>, EmittedFrom<TLogic>>
{
/**
* The current internal state of the actor.
Expand Down Expand Up @@ -106,7 +107,11 @@ export class Actor<TLogic extends AnyActorLogic>
public _parent?: AnyActorRef;
/** @internal */
public _syncSnapshot?: boolean;
public ref: ActorRef<SnapshotFrom<TLogic>, EventFromLogic<TLogic>>;
public ref: ActorRef<
SnapshotFrom<TLogic>,
EventFromLogic<TLogic>,
EmittedFrom<TLogic>
>;
davidkpiano marked this conversation as resolved.
Show resolved Hide resolved
// TODO: add typings for system
private _actorScope: ActorScope<
SnapshotFrom<TLogic>,
Expand Down
24 changes: 14 additions & 10 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ export interface UnifiedArg<
unknown,
TODO // TMeta
>,
TEvent
TEvent,
AnyEventObject
>;
system: AnyActorSystem;
}
Expand Down Expand Up @@ -169,7 +170,7 @@ export type OutputFrom<T> = T extends ActorLogic<
infer _TEmitted
>
? (TSnapshot & { status: 'done' })['output']
: T extends ActorRef<infer TSnapshot, infer _TEvent>
: T extends ActorRef<infer TSnapshot, infer _TEvent, infer _TEmitted>
davidkpiano marked this conversation as resolved.
Show resolved Hide resolved
? (TSnapshot & { status: 'done' })['output']
: never;

Expand Down Expand Up @@ -1521,7 +1522,8 @@ export type ContextFactory<
unknown,
TODO // TMeta
>,
TEvent
TEvent,
AnyEventObject
>;
}) => TContext;

Expand Down Expand Up @@ -1827,7 +1829,8 @@ export type Mapper<
unknown,
TODO // TMeta
>,
TEvent
TEvent,
AnyEventObject
>;
}) => TResult;

Expand Down Expand Up @@ -2181,7 +2184,7 @@ export interface ActorRef<
) => Subscription;
}

export type AnyActorRef = ActorRef<any, any>;
export type AnyActorRef = ActorRef<any, any, any>;

export type ActorLogicFrom<T> = ReturnTypeOrValue<T> extends infer R
? R extends StateMachine<
Expand Down Expand Up @@ -2232,7 +2235,8 @@ export type ActorRefFrom<T> = ReturnTypeOrValue<T> extends infer R
TOutput,
TMeta
>,
TEvent
TEvent,
TEmitted
>
: R extends Promise<infer U>
? ActorRefFrom<PromiseActorLogic<U>>
Expand All @@ -2243,7 +2247,7 @@ export type ActorRefFrom<T> = ReturnTypeOrValue<T> extends infer R
infer _TSystem,
infer TEmitted
>
? ActorRef<TSnapshot, TEvent>
? ActorRef<TSnapshot, TEvent, TEmitted>
: never
: never;

Expand Down Expand Up @@ -2341,7 +2345,7 @@ export interface ActorScope<
TSystem extends AnyActorSystem = AnyActorSystem,
TEmitted extends EventObject = EventObject
> {
self: ActorRef<TSnapshot, TEvent>;
self: ActorRef<TSnapshot, TEvent, TEmitted>;
id: string;
sessionId: string;
logger: (...args: any[]) => void;
Expand Down Expand Up @@ -2469,7 +2473,7 @@ export type UnknownActorLogic = ActorLogic<
>;

export type SnapshotFrom<T> = ReturnTypeOrValue<T> extends infer R
? R extends ActorRef<infer TSnapshot, infer _>
? R extends ActorRef<infer TSnapshot, infer _, infer __>
? TSnapshot
: R extends Actor<infer TLogic>
? SnapshotFrom<TLogic>
Expand Down Expand Up @@ -2541,7 +2545,7 @@ type ResolveEventType<T> = ReturnTypeOrValue<T> extends infer R
infer _TMeta
>
? TEvent
: R extends ActorRef<infer _, infer TEvent>
: R extends ActorRef<infer _TSnapshot, infer TEvent, infer _TEmitted>
? TEvent
: never
: never;
Expand Down
16 changes: 15 additions & 1 deletion packages/core/test/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
sendTo,
spawnChild,
stateIn,
setup
setup,
toPromise
} from '../src/index';

function noop(_x: unknown) {
Expand Down Expand Up @@ -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);
});
4 changes: 2 additions & 2 deletions packages/xstate-solid/src/fromActorRef.ts
Original file line number Diff line number Diff line change
@@ -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<TActor extends ActorRef<any, any> | undefined>(
export function fromActorRef<TActor extends AnyActorRef | undefined>(
actorRef: Accessor<TActor> | TActor
): Accessor<
| SnapshotFrom<NonNullable<TActor>>
Expand Down
Loading