0

I have this DB, and I'm trying correctly map the types when using Map function. First time doing it so trying to learn but I'm stuck.

Db

const db = {
  data: [
    {
      id: 1,
      contentType: ['video'],
      title: '1 to 1 Coaching: Sprinting Technique',
      author: {
        name: 'James',
        image: {
          alt: 'smiling.',
        },
      },
      image: {
        alt: 'Two footballers jostling for the ball with a coach watching in the background.',
      },
    },
  ],
}

For now I'm just using sample type of id and title but even here I'm stuck on how to correctly map it so TS does not complain :(

App.tsx

type Data = {
  id: number
  title: string
}

interface Customer {
  id: number
  title: string
}

export default function Box(): JSX.Element {
  const [data, setData] = useState([db])
  return (
    <>
      {data.map(
        ({
          data: {
            id,
            contentType,
            title,
            author: {
              name,
              img: { src, alt },
            },
            image: { src, alt },
          },
        }): JSX.Element => {
          console.log(id)
          return <div css={mainBox}></div>
        },
      )}
    </>
  )
}
5
  • Please create a small demo for this using codesandbox.io to show the issue happening. Commented May 15, 2020 at 15:00
  • Why are you creating a single-element array to iterate over? What's TypeScript's complaint? Commented May 15, 2020 at 15:02
  • codesandbox.io/s/silly-frost-r46zl?file=/src/index.tsx Commented May 15, 2020 at 15:03
  • single element is an example it will have more from DB. Updated map to include all elements, i believe this is how it should look correct me if I'm wrong Commented May 15, 2020 at 15:04
  • There's a data[x].author.image in your db, but a data[x].author.img in Box(). Commented May 15, 2020 at 19:05

1 Answer 1

1

This issue has little to do with TS itself since the error is at object destructuring in parameters list of your map callback.

When you apply object destructuring to the argument of the function, JS/TS assigns properties of the object to distinct variables with the same name (unless they are objects and they are destructured in a similar way).

Let's have a look at author property destructuring:

...
            author: {
              name,
              img: { src, alt },
            },
...

This snippet will be treated as following:

author.name property will be assigned to distinct name variable. However,

author.img won't be assigned to distinct img variable since it is an object and it is desctructured. It's properties would be assigned to distinct variables src and alt respectively.

After that we have another property desturctured:

    image: { src, alt },

Again, image won't be assigned to distinct variable since it's object being destructured. But it's properties should.

It's properties are src and alt. And they should be set to variables with these names but we already have those names come from destructuring author.img.

So there is name collision in variables definition and that's why TS compiler raised an error.

You may fix this by assigning properties to new variable names, for example, the following way:

({
          data: {
            id,
            contentType,
            title,
            author: {
              name,
              img: { src: authorImgSrc, alt: authorImgAlt },
            },
            image: { src, alt },
          },
        }): JSX.Element => {
            // src refers to image.src, authorImgSrc refers to author.name.src
            // alt refers to image.alt, authorImgAlt refers to author.name.alt
        }

Here we explicitly assigned author.img properties to variables with different names so there is no name collision anymore.

The destructuring assignment technique might be really useful, there are more examples of it on MDN

After that you might see that you might not even need map in the first place, because you used array destructuring here:

const [data] = useState([db]);

And after that you may have access to it's internals directly:

const {img} = data.data.author;

So you may want to either remove .map (and render db entry directly) or not use array destructuring in data variable initialization:

const data = useState([db]);
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.