#Can I have type of one field depend on the value of another?

6 messages · Page 1 of 1 (latest)

supple sphinx
#

I might be missing something basic here, and I'm not really sure what to search for. Can I define an object type where the type of one field depends on the value of another? A helper function would be fine too. Here's some mock code using this as a placeholder for what I want:

type Workflow = {
  firstStep: keyof this.steps;
  steps: {
    component: [key: string]: (props: { value: any, [prop: string]: any }) => ReactNode;
    next: keyof this.steps | null;
  };
  checkIfValid: (stepValues: {
    [StepKey in keyof this.steps]: Parameters<this.steps[StepKey]['component']>[0]['value'];
  }) => boolean;
};

const wf: Workflow = {
  firstStep: 'name', // The first step must be a key in `steps`.

  steps: {
    // Each step's component needs a `value` prop.
    name: {
      component({ value }: { value: string }) {
        return <input value={value} />;
      },
      next: 'age', // Must be a `steps` key or `null`.
    },

    age: {
      component({ value }: { value: number }) {
        return <input value={value} />;
      },
      next: null,
    },
  },

  checkIfValid({ name, age }) {
    // Here we'd know the `name` is a string and `age` is a number.
    return name === 'Admin' && age > 100;
  },
}
hazy thistle
#

You can't really have this as a direct type I think but you can have it checked by a CIF

#

(trying to write a poc)

compact gustBOT
#
angryzor#9490

Preview:```ts
import React, {ComponentProps, FC} from "react"

type Step<StepName> = {
component: FC<{value: never; [prop: string]: never}>
next: StepName | null
}

type Steps<StepName extends string = string> = Record<
StepName,
Step<StepName>

type Workflow<T extends {steps: Steps}> = {
firstStep:
...```

hazy thistle
#

@supple sphinx

supple sphinx
#

Real close, but I'd love if checkIfValid's argument type could be inferred from steps's component props. It looks like [StepKey in keyof T['steps'] & string]: ComponentProps<T['steps'][StepKey]['component']>['value'] would do that, but no dice.