form icon indicating copy to clipboard operation
form copied to clipboard

DeepKeys produces keys incompatible with DeepValue

Open rodogir opened this issue 1 year ago • 3 comments

Describe the bug

I noticed the bug when trying to use the Field component with a static name that points to a property inside of an array (e.g. friends.0.name). The useField hook and Field component will claim that the name prop is invalid, even though they function correctly. This is due how DeepKeys is defined. Further, I also noticed that DeepValue correctly handles array keys.

Your minimal, reproducible example

codesandbox

Steps to reproduce

DeepKeys problem

  1. Go to /src/example.spec.ts
  2. Look at the code and notice that type issues when trying to use DeepValue with DeepKeys

To see that Field works with array keys:

  1. Run the linked codesanbox
  2. You will see 2 input fields, change second one ("Robin") to whatever you want.
  3. Hit the submit button
  4. Check the console and verify that the values are as expected.
  5. The source code is under /src/App.tsx

Expected behavior

I expect DeepKeys to produce keys that are compatible with DeepValue. Also, I should be able to use Field with a key containing array indexes (e.g. friends.${number}.name).

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

It's a type issue and platform independent.

Tanstack Form adapter

None

TanStack Form version

0.13.3

TypeScript version

5.2.2

Additional context

No response

rodogir avatar Jan 12 '24 12:01 rodogir

Technically you're not supposed to use DeepKeys and DeepValue outside of the internals of the library. They're exposed because they're how we build out the types and have to be to make the types "portable".

Also, the API you're trying to use with a number being part of the name isn't valid in framework adapters for this reason (IIRC). There's likely some work we need to do to clarify this (even probably changing the API).

crutchcorn avatar Jan 12 '24 18:01 crutchcorn

Thanks for the clarification.

I'd like to provide some context for you to understand where we are coming from. We are building reusable, form-connected and type-safe input components. Here's an usage example:

function Example() {
  const form = useForm({
    defaultValues: {
      firstName: 'John',
      lastName: 'Doe',
      age: 42,
    }
  });

  return (
    <form>
      <FormTextField form={form} name="firstName" />
      <FormTextField form={form} name="lastName" />
      <FormNumberField form={form} name="age" />
    </form>
  );
}

We rely on DeepKeys and DeepValue to enforce type safety. For example, FormTextField accepts only names with string values, while FormNumberField is restricted to names with number values. This greatly improves our DX.

However, since DeepKeys and DeepValue are internal, I'm concerned about the sustainability of our approach. Are there alternative, officially supported methods for achieving similar levels of type safety with form components?

rodogir avatar Jan 15 '24 09:01 rodogir

Agreed that this usage is the right way to go. It's how our docs will eventually encourage people to use TanStack Form.

Let's chat more in our Discord about how we can make this process easier and smoother for you (and others!). It might mean continuing to rely on DeepKeys and DeepValue for now but we introduce a more stable API in the future.

If nothing else, it'll help us shape what our docs should look like for this scenario.

crutchcorn avatar Jan 15 '24 23:01 crutchcorn

This issue with the typings should not occur anymore. However, ignoring that, we'll be working on documenting in-house library usage prior to 1.x

Closing since we should discuss that in a different issue

crutchcorn avatar Mar 18 '24 08:03 crutchcorn