0

In my component Product.tsx I receive an object via API call that could look like this:

{
  title: "Product 1",
  status: "active",
  tax: true,
  variants: [
    {
      id: 1,
      sku: 'PRD1',
      price: 24.00,
      price_reduced: 19.95,
      size: 'M'
    },
    {
      id: 2,
      sku: 'PRD2',
      price: 24.00,
      price_reduced: 19.95
      size: 'L'
    },
  ]
}

I then render each variant as a row in a table where each column displays the price, size etc. as editable input fields. onChange of each input triggers updateVariant(variant.id, key, e); where key is one of the keys of a variant and e is the input event.

updateVariant should update the value of a variant with the given key and looks like this:

  const updateVariant = (
    id: number,
    key: string,
    e: React.FormEvent<HTMLInputElement>
  ) => {
    setProduct((prevState) => {
      const update = { ...prevState };
      const i = update.variants.findIndex((variant) => variant.id === id);
      const updatedVariant = update.variants[i];
      updatedVariant[key] = e.currentTarget.value;   // errors on this line
      update.variants[i] = udpatedVariant;
      return update;
    });
  };

It gives me an error on updatedVariant[key] = e.currentTarget.value;:

Element implicitly has 'any' type because expression of type 'string | number' can't be
used to index type '{id: number, sku: string, ...}'. No index signature with a parameter
of type 'string' was found on type '{id: number, sku: string ...}'

I tried changing it to: updatedVariant[key as keyof typeof updatedVariant] = e.currentTarget.value; which gives me the error type 'any' is not assignable to type 'never'

I am quite new to Typescript and completely lost how to make this work.

EDIT: I got it to work temporarily with

updatedVariant[key as keyof typeof updatedVariant] = e.currentTarget.value as never;

But this can't be the right / clean solution to this?

1
  • 1
    try updatedVariant[key] = e.currentTarget.value as number | string; Commented Oct 7, 2021 at 14:59

1 Answer 1

3

I got it working by declaring an interface like so:

interface Variant {
  [key: string]: string | number | string[];
}

and then

(updatedVariant as Variant)[key] = e.currentTarget.value;

My mistake was to think that key was missing a type or something when in fact I needed an interface for updatedVariant.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.