Skip to content

Commit

Permalink
Fixed an issue with contextual parameters in input factories of input…
Browse files Browse the repository at this point in the history
…-less actors (#4523)

* Fixed an issue with contextual parameters in input factories of input-less actors

* Changeset

---------

Co-authored-by: David Khourshid <[email protected]>
  • Loading branch information
Andarist and davidkpiano authored Nov 30, 2023
1 parent 63d9238 commit e21e3f9
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/khaki-bees-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': patch
---

Fixed an issue with contextual parameters in input factories of input-less actors
14 changes: 9 additions & 5 deletions packages/core/src/actors/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
ActorSystem,
ActorRefFrom,
Snapshot,
AnyActorRef
AnyActorRef,
NonReducibleUnknown
} from '../types';
import { XSTATE_STOP } from '../constants.ts';

Expand All @@ -26,12 +27,12 @@ export type CallbackSnapshot<TInput> = Snapshot<undefined> & {

export type CallbackActorLogic<
TEvent extends EventObject,
TInput = unknown
TInput = NonReducibleUnknown
> = ActorLogic<CallbackSnapshot<TInput>, TEvent, TInput, ActorSystem<any>>;

export type CallbackActorRef<
TEvent extends EventObject,
TInput = unknown
TInput = NonReducibleUnknown
> = ActorRefFrom<CallbackActorLogic<TEvent, TInput>>;

export type Receiver<TEvent extends EventObject> = (
Expand All @@ -43,7 +44,7 @@ export type Receiver<TEvent extends EventObject> = (
export type InvokeCallback<
TEvent extends EventObject = AnyEventObject,
TSentEvent extends EventObject = AnyEventObject,
TInput = unknown
TInput = NonReducibleUnknown
> = ({
input,
system,
Expand Down Expand Up @@ -132,7 +133,10 @@ export type InvokeCallback<
* });
* ```
*/
export function fromCallback<TEvent extends EventObject, TInput = unknown>(
export function fromCallback<
TEvent extends EventObject,
TInput = NonReducibleUnknown
>(
invokeCallback: InvokeCallback<TEvent, AnyEventObject, TInput>
): CallbackActorLogic<TEvent, TInput> {
const logic: CallbackActorLogic<TEvent, TInput> = {
Expand Down
20 changes: 15 additions & 5 deletions packages/core/src/actors/observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,27 @@ import {
Subscription,
AnyActorSystem,
ActorRefFrom,
Snapshot
Snapshot,
NonReducibleUnknown
} from '../types';

const XSTATE_OBSERVABLE_NEXT = 'xstate.observable.next';
const XSTATE_OBSERVABLE_ERROR = 'xstate.observable.error';
const XSTATE_OBSERVABLE_COMPLETE = 'xstate.observable.complete';

export type ObservableSnapshot<TContext, TInput> = Snapshot<undefined> & {
export type ObservableSnapshot<
TContext,
TInput extends NonReducibleUnknown
> = Snapshot<undefined> & {
context: TContext | undefined;
input: TInput | undefined;
_subscription: Subscription | undefined;
};

export type ObservableActorLogic<TContext, TInput> = ActorLogic<
export type ObservableActorLogic<
TContext,
TInput extends NonReducibleUnknown
> = ActorLogic<
ObservableSnapshot<TContext, TInput>,
{ type: string; [k: string]: unknown },
TInput,
Expand Down Expand Up @@ -70,7 +77,7 @@ export type ObservableActorRef<TContext> = ActorRefFrom<
* @see {@link https://rxjs.dev} for documentation on RxJS Observable and observable creators.
* @see {@link Subscribable} interface in XState, which is based on and compatible with RxJS Observable.
*/
export function fromObservable<TContext, TInput>(
export function fromObservable<TContext, TInput extends NonReducibleUnknown>(
observableCreator: ({
input,
system
Expand Down Expand Up @@ -214,7 +221,10 @@ export function fromObservable<TContext, TInput>(
* canvasActor.start();
* ```
*/
export function fromEventObservable<T extends EventObject, TInput>(
export function fromEventObservable<
T extends EventObject,
TInput extends NonReducibleUnknown
>(
lazyObservable: ({
input,
system
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/actors/promise.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { XSTATE_STOP } from '../constants';
import {
ActorLogic,
ActorRefFrom,
ActorSystem,
AnyActorSystem,
NonReducibleUnknown,
Snapshot
} from '../types';
import { XSTATE_STOP } from '../constants';

export type PromiseSnapshot<TOutput, TInput> = Snapshot<TOutput> & {
input: TInput | undefined;
Expand Down Expand Up @@ -82,8 +83,7 @@ export type PromiseActorRef<TOutput> = ActorRefFrom<
* // }
* ```
*/
export function fromPromise<TOutput, TInput = unknown>(
// TODO: add types
export function fromPromise<TOutput, TInput = NonReducibleUnknown>(
promiseCreator: ({
input,
system
Expand Down
7 changes: 4 additions & 3 deletions packages/core/src/actors/transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
EventObject,
ActorRefFrom,
AnyActorSystem,
Snapshot
Snapshot,
NonReducibleUnknown
} from '../types';

export type TransitionSnapshot<TContext> = Snapshot<undefined> & {
Expand All @@ -15,7 +16,7 @@ export type TransitionSnapshot<TContext> = Snapshot<undefined> & {
export type TransitionActorLogic<
TContext,
TEvent extends EventObject,
TInput
TInput extends NonReducibleUnknown
> = ActorLogic<TransitionSnapshot<TContext>, TEvent, TInput, AnyActorSystem>;

export type TransitionActorRef<
Expand Down Expand Up @@ -87,7 +88,7 @@ export function fromTransition<
TContext,
TEvent extends EventObject,
TSystem extends ActorSystem<any>,
TInput
TInput extends NonReducibleUnknown
>(
transition: (
state: TContext,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
SetupTypes,
StateSchema,
ToChildren,
UnknownActorLogic,
Values
} from './types';

Expand Down Expand Up @@ -102,7 +103,7 @@ type ToStateValue<T extends StateSchema> = T extends {
export function setup<
TContext extends MachineContext,
TEvent extends AnyEventObject, // TODO: consider using a stricter `EventObject` here
TActors extends Record<Values<TChildrenMap>, AnyActorLogic>,
TActors extends Record<Values<TChildrenMap>, UnknownActorLogic>,
TActions extends Record<string, ParameterizedObject['params'] | undefined>,
TGuards extends Record<string, ParameterizedObject['params'] | undefined>,
TDelay extends string,
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2123,7 +2123,7 @@ export type Snapshot<TOutput> =
export interface ActorLogic<
TSnapshot extends Snapshot<unknown>,
TEvent extends EventObject,
TInput = unknown,
TInput = NonReducibleUnknown,
TSystem extends ActorSystem<any> = ActorSystem<any>
> {
/** The initial setup/configuration used to create the actor logic. */
Expand All @@ -2137,7 +2137,7 @@ export interface ActorLogic<
* @returns The new state.
*/
transition: (
state: TSnapshot,
snapshot: TSnapshot,
message: TEvent,
ctx: ActorScope<TSnapshot, TEvent, TSystem>
) => TSnapshot;
Expand Down Expand Up @@ -2184,6 +2184,13 @@ export type AnyActorLogic = ActorLogic<
any // system
>;

export type UnknownActorLogic = ActorLogic<
any, // this is invariant and it's hard to figure out a better default than `any`
EventObject,
NonReducibleUnknown,
ActorSystem<any>
>;

export type SnapshotFrom<T> = ReturnTypeOrValue<T> extends infer R
? R extends ActorRef<infer _, infer TSnapshot>
? TSnapshot
Expand Down
22 changes: 22 additions & 0 deletions packages/core/test/setup.types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,28 @@ describe('setup()', () => {
});
});

it(`should provide contextual parameters to input factory for an actor that doesn't specify any input`, () => {
setup({
types: {
context: {} as { count: number }
},
actors: {
child: fromPromise(() => Promise.resolve(1))
}
}).createMachine({
context: { count: 1 },
invoke: {
src: 'child',
input: ({ context }) => {
// @ts-expect-error
context.foo;

return undefined;
}
}
});
});

it('should return the correct child type on the available snapshot when the child ID for the actor was configured', () => {
const child = createMachine({
types: {} as {
Expand Down

0 comments on commit e21e3f9

Please sign in to comment.