xstate icon indicating copy to clipboard operation
xstate copied to clipboard

Bug: higher-order guards types do not allow dynamic params

Open florian-lefebvre opened this issue 2 years ago • 5 comments

Description

When using guard params (https://stately.ai/docs/guards#guard-object), they need to be called as an object. But higher order guards like not do not support them at the Type Level.

Expected result

              guard: and([
                not({
                  type: "isGuessValid",
                  params: ({ event }) => ({ index: event.index }),
                }),
                not("isLetterUsed"),
              ]),

To not throw any TS error

Actual result

Type 'GuardPredicate<{ chars: { content: string; guessIndex?: number | undefined; }[]; guess: { content: string; valid?: boolean | undefined; }[]; solution: string[]; }, { type: "addLetter"; index: number; }, unknown, { type: "isLetterUsed"; params: undefined; } & ParameterizedObject>' is not assignable to type 'Guard<{ chars: { content: string; guessIndex?: number | undefined; }[]; guess: { content: string; valid?: boolean | undefined; }[]; solution: string[]; }, { type: "addLetter"; index: number; }, undefined, { ...; } | ... 1 more ... | { ...; }> | undefined'.

Reproduction

https://tsplay.dev/Wo13LN

Additional context

See https://discord.com/channels/795785288994652170/1181599123112210512

florian-lefebvre avatar Dec 06 '23 09:12 florian-lefebvre

This one is quite hard to fix - as mentioned on Discord. So far I failed to figure out anything but I'll continue trying.

Andarist avatar Dec 06 '23 15:12 Andarist

So I got some news. I managed to provide the contextual parameter type in a situation like this in a standalone repro of the problem: TS playground. This widens (at least in this scenario) type: 'checkFoo' and it becomes type: string - which in turn breaks type-checking. It can be fixed~ by slapping some as const on it but it would be best if we could avoid this.

Andarist avatar Dec 11 '23 10:12 Andarist

Oh, and I can bring back this string literal narrowing by introducing TType extends string, like here: TS playground. I'm not yet sure how this technique will scale with and and or though.

Andarist avatar Dec 11 '23 10:12 Andarist

I'm appalled by this but this one seems to work: TS playground

Andarist avatar Dec 11 '23 11:12 Andarist