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

Narrowing DeepKeys based on value type #1070

Open
lrondini-fae opened this issue Dec 13, 2024 · 0 comments
Open

Narrowing DeepKeys based on value type #1070

lrondini-fae opened this issue Dec 13, 2024 · 0 comments

Comments

@lrondini-fae
Copy link

I would like to create a React component that returns a ReactFormExtendedApi.Form component containing an <input> field, passing down to that input some attributes such as the value (field.state.value) and onChange function (field.handleChange(v)).

Since this component returns an input field, it should accept only form keys whose value is of type string in the current form.

I am having problems in achieving that with TypeScript. This is the FormInput code:

import {
  DeepKeys,
  DeepValue,
  ReactFormExtendedApi,
} from "@tanstack/react-form";

type TypedDeepKeys<S, T> = Exclude<
  {
    [K in DeepKeys<S>]: DeepValue<S, K> extends T ? K : never;
  }[DeepKeys<S>],
  number
>;

export const FormInput = <FormData, K extends TypedDeepKeys<FormData, string>>({
  form,
  fieldKey,
}: {
  form: ReactFormExtendedApi<FormData>;
  fieldKey: K;
}) => {
  return (
    <form.Field
      name={fieldKey}
      children={(field) => (
        <input
          value={field.state.value}
          onChange={(v) => field.handleChange(v)}
          onBlur={field.handleBlur}
          name={fieldKey}
        />
      )}
    />
  );
};

As you can see, there is a type (TypedDeepKeys) that should narrow the accepted keys of the form schema to those that accept a string value.

However, it seems that TypeScript does not recognize that with this constraint the field.state.value can only be a string, as I get the following error:

Type 'DeepValue<FormData, K, IsNullable<FormData>>' is not assignable to type 'string | number | readonly string[] | undefined'.
  Type 'FormData | (FormData extends readonly any[] ? K extends `[${infer TBrackets}].${infer TAfter}` ? DeepValue<DeepValue<FormData, TBrackets, IsNullable<FormData>>, TAfter, IsNullable<...>> : K extends `[${infer TBrackets}]` ? DeepValue<...> : K extends keyof FormData ? FormData[K] : FormData[K & number] : FormData exte...' is not assignable to type 'string | number | readonly string[] | undefined'.
    Type 'FormData' is not assignable to type 'string | number | readonly string[] | undefined'.
      Type 'FormData' is not assignable to type 'readonly string[]'.
        Type 'DeepValue<FormData, K, IsNullable<FormData>>' is not assignable to type 'readonly string[]'.
          Type 'FormData | (FormData extends readonly any[] ? K extends `[${infer TBrackets}].${infer TAfter}` ? DeepValue<DeepValue<FormData, TBrackets, IsNullable<FormData>>, TAfter, IsNullable<...>> : K extends `[${infer TBrackets}]` ? DeepValue<...> : K extends keyof FormData ? FormData[K] : FormData[K & number] : FormData exte...' is not assignable to type 'readonly string[]'.

            Type 'FormData' is not assignable to type 'readonly string[]'.

Looks like that the type of field.state.value may also be FormData, but this doesn't make sense.
Is there something that I'm missing?

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

No branches or pull requests

1 participant