Skip to content

[v2] Support type narrowing for union form types #2297

Description

@LeCarbonator

In v2, a component may need to accept a form created from one of several sets of form options:

const formVariant1 = formOptions(/* ... */)
const formVariant2 = formOptions(/* ... */)

type Form1 = ReactFormType<typeof formVariant1>
type Form2 = ReactFormType<typeof formVariant2>


interface MyComponentProps {
  form: Form1 | Form2
}

TypeScript cannot resolve the resulting union of form types correctly. Once form is typed as Form1 | Form2, members such as form.Field are no longer available.

A related problem occurs when a form's values are represented by a union. Even after checking a discriminant, such as form.state.values.type === 'A', TypeScript does not narrow the type of the form itself. APIs that are only valid for type A therefore remain unavailable even though the value has already been narrowed.

It would be useful to have an API that narrows the form alongside its values. A user could provide a type predicate for one member of the union and, when that predicate succeeds, work with a form typed specifically for that member.

Some thoughts

The exact API is open for discussion, but a possible design would:

  • accept formOptions whose data type is a union;
  • accept a callback that acts as a type predicate, narrowing TData to one of its members (TGuard);
  • expose a form type narrowed to TGuard; and
  • provide a function, essentially a wrapper around the original predicate, that can accept the TData form and narrow it to the corresponding TGuard form.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: typesThis issue affects the types of the library.scope: coreThis issue affects the core package, meaning any adapter is also affected by it.type: enhancementThis requests an enhancement to existing behaviour.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions