reactjs - Använda generiska som metodargument i diskriminerade unioner


Låt oss säga att vi har en diskriminerad union som accepterar ett argument av sig själv:

type TextInput<Props extends Inputs<Props>> = {
    type: 'text',
    value?: string,
    options?: undefined
}

type CheckboxInput<Props extends Inputs<Props>> = {
    type: 'checkbox',
    options: string[] | number[],
    value?: Props['options'] extends Array<infer T> ? T : never
}

type Events<Props extends Inputs<Props>> = { onInput?: (arg: Inputs<Props>['value']) => any }

type Inputs<Props extends Inputs<Props>> = TextInput<Props> | CheckboxInput<Props>

Detta fungerar, och vi kan göra några ganska anmärkningsvärda saker:

type Make = <P extends Inputs<P>>(props: P) => {}

declare const create: Make

create({ type: 'text', value: '123' })  // 👍
create({ type: 'text', value: 123 }) // 👍 (value must be a string)
                       ^^^^^^^^^^
create({ type: 'checkbox', options: ['a', 'b'], value: 'a' }) // 👍
create({ type: 'checkbox', options: [1, 2, 3], value: 2 }) // 👍
create({ type: 'checkbox', options: ['a', 'b'], value: 2 }) // 👍 (value must match options type)
                                                ^^^^^^^^

Men jag skulle vilja lägga till en metod till den diskriminerade unionen och säkerställa att argumentet till den metoden också matchar värdetypen. Detta verkar inte vara möjligt:

type TextInput<Props extends Inputs<Props>> = {
    type: 'text',
    value?: string,
    options?: undefined
} & Events<Props>

type CheckboxInput<Props extends Inputs<Props>> = {
    type: 'checkbox',
    options: string[] | number[],
    value?: Props['options'] extends Array<infer T> ? T : never
} & Events<Props>

type Events<Props extends Inputs<Props>> = { onInput?: (arg: Inputs<Props>['value']) => any }

type Inputs<Props extends Inputs<Props>> = TextInput<Props> | CheckboxInput<Props>

type Make = <P extends Inputs<P>>(props: P) => {}

declare const create: Make

create({ type: 'checkbox', options: [1, 2, 3], value: 1, onInput: (arg) => arg }) // 👎 "arg" in onInput should only be a number, matching the value type

Fråga: Finns det något sätt att använda den inskränkta union-datan som argument för en metod inuti unionen?

Fullständig TypeScript-lekplats