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

Ensure that context is defined when model type provided to createMachine() #2334

Merged
merged 3 commits into from
Jun 25, 2021

Conversation

davidkpiano
Copy link
Member

@davidkpiano davidkpiano commented Jun 24, 2021

When using a model type in createMachine<typeof someModel>(...), TypeScript will no longer compile machines that are missing the context property in the machine configuration:

const machine = createMachine<typeof someModel>({
  // missing context - will give a TS error!
  // context: someModel.initialContext,
  initial: 'somewhere',
  states: {
    somewhere: {}
  }
});

@changeset-bot
Copy link

changeset-bot bot commented Jun 24, 2021

🦋 Changeset detected

Latest commit: 38e6a5e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
xstate Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

id: 'machine',
initial: 'inactive',
// missing context:
// context: toggleModel.initialContext,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question that I feel is somewhat related to this.

There are cases for which the initial context is not known upfront - for example when the machine requires user data but it can only be passed from the parent since it first needs to be acquired from somewhere. With this change, you force a user to provide some dummy data here or you steer them towards casting which loses the type safety. Of course, currently, there is no type safety when you don't provide any context value, and yet you expect context to be of a certain type but that is an orthogonal problem. And it has existed before the model has even been introduced.

So the question is - what the user should do when using modal for cases like the one that I've described. What's the official recommendation?

Copy link
Member Author

@davidkpiano davidkpiano Jun 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this pattern, that's not an issue:

const createUserMachine = user => createMachine({
  context: { user }
});

And with a model:

const createUserMachine = user => {
  const model = createModel({ user });

  return createMachine<typeof model>({
    context: model.initialContext
  });
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another idea (from Discord) for reference:

// TENTATIVE API
const machine = createMachine({
  // input is of type Partial<TContext> maybe
  context: (input) => ({
    some: 'default value',
    ...input
  })
});

machine.transition(/* ... */); // throws error; expecting input

machine.withContext({ the: 'input' }).transition(/* ... */);

interpret(machine); // throws error

interpret(machine.withContext({ ... })); // does not throw error

@davidkpiano davidkpiano mentioned this pull request Jun 25, 2021
@davidkpiano davidkpiano merged commit ef8927a into main Jun 25, 2021
@github-actions github-actions bot mentioned this pull request Jun 25, 2021
@Andarist Andarist deleted the davidkpiano/model-required-context branch March 22, 2023 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants