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

enqueue.assign() is not typesafe #4810

Open
ivankoleda opened this issue Mar 20, 2024 · 4 comments
Open

enqueue.assign() is not typesafe #4810

ivankoleda opened this issue Mar 20, 2024 · 4 comments
Assignees

Comments

@ivankoleda
Copy link

XState version

XState version 5

Description

If we define types in setup function like this

setup({
    types: {} as {
      context: {
        foo: {
          bar: string;
        };
      };
    },
  })

And add a following action handler

 actions: [
  enqueueActions(({ enqueue }) => {
    enqueue.assign({
      // No TS error
      foo: undefined,
    });
  }),
],

There won't be a type error and accessing context.foo.bar will result in runtime error as context.foo can be undefined during runtime.

Doing the same with assign results in type error though:

actions: [
  assign({
    // TS error
    foo: () => undefined,
  })
]

Expected result

Typescript error

Actual result

No Typescript error

Reproduction

https://stackblitz.com/edit/vitejs-vite-jwifv4?file=src%2Fmain.ts

Additional context

No response

@Andarist
Copy link
Member

You are not comparing the same flavor of assign here. If we want to compare the same flavors then we need to compare those two:

assign({
  foo: undefined,
}),
enqueueActions(({ enqueue }) => {
  enqueue.assign({
    foo: undefined,
  });
}),

And they both don't error here. The problem is that assign accepts a "partial assigned" - u are free to pass just some keys (and not everything the context has). The problem here is that TS (by default) always allows undefined value for optional properties (and Partial creates optional properties). One needs exactOptionalPropertyTypes to change this behavior and not many projects have that setting enabled.

@Andarist
Copy link
Member

We can't address this as long as we allow property assigners derived from Partial<TContext>. So the Bug label here isn't quite fitting (cc @davidkpiano). It feels like a design limitation with the current API.

@davidkpiano
Copy link
Member

I added the recommendation to use exactOptionalPropertyTypes in the TypeScript documentation https://stately.ai/docs/typescript#set-up-your-tsconfigjson-file

{
  "compilerOptions": {
    // ...
    "strictNullChecks": true,
    // or set `strict` to true, which includes `strictNullChecks`
    // "strict": true,
    "skipLibCheck": true,
    "exactOptionalPropertyTypes": true
  }
}

@Andarist
Copy link
Member

@davidkpiano this likely should be removed from the docs for the time being since our types are actually not fully compatible with this flag, see #4613

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants