Bug
Following fairly closely the TODO example the following code won't accept what I wrote for the "onEntry":
import { Machine, actions, EventObject } from "xstate";
const { assign } = actions;
export interface TagContext {
title: string;
previousTitle: string | null;
}
export type EventId = "COMMIT";
export interface TagEvent extends EventObject {
type: EventId;
}
export const TagMachine = Machine<TagContext,any,TagEvent>({
id: "tag",
initial: "editing",
context: {
previousTitle: null,
title: ""
},
states: {
editing: {
onEntry: assign({ previousTitle: ctx => ctx.title }),
on: {
COMMIT: {
target: "viewing"
}
}
}
}
})
Should compile
Argument of type '{ previousTitle: (ctx: TagContext) => string; }' is not assignable to parameter of type 'Assigner<{ previousTitle: string; }, TagEvent> | Partial<{ previousTitle: string | ((context: { previousTitle: string; }, event: TagEvent) => string); }>'.
Type '{ previousTitle: (ctx: TagContext) => string; }' is not assignable to type 'Partial<{ previousTitle: string | ((context: { previousTitle: string; }, event: TagEvent) => string); }>'.
Types of property 'previousTitle' are incompatible.
Type '(ctx: TagContext) => string' is not assignable to type 'string | ((context: { previousTitle: string; }, event: TagEvent) => string) | undefined'.
Type '(ctx: TagContext) => string' is not assignable to type '(context: { previousTitle: string; }, event: TagEvent) => string'.
Types of parameters 'ctx' and 'context' are incompatible.
Property 'title' is missing in type '{ previousTitle: string; }' but required in type 'TagContext'.ts(2345)
Somewhere the type definition derails, but I am not actually sure where.
This is typescript 3.4.5 and xstate 4.5.0
Workaround:
onEntry: assign<TagContext>({
// your assignments here
})
I believe that TypeScript still has a hard time narrowing type definitions inferred from functions; that is, if we can expect AssignObject<TContext> but we are given a function that returns AssignObject<any>, TS sometimes has a hard time narrowing that any to a TContext.
Could this be documented somehow in the ts guide ?
It is, the docs just aren't published yet: https://github.com/davidkpiano/xstate/blob/master/docs/guides/context.md#typescript
Thank you 馃檹
Most helpful comment
Workaround:
I believe that TypeScript still has a hard time narrowing type definitions inferred from functions; that is, if we can expect
AssignObject<TContext>but we are given a function that returnsAssignObject<any>, TS sometimes has a hard time narrowing thatanyto aTContext.