如何将TypeScript正确用于地图功能?

时间:2020-05-15 15:00:00

标签: javascript reactjs typescript types

我有这个数据库,在使用Map函数时我正在尝试正确地映射类型。第一次这样做是为了尝试学习,但我被困住了。

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.',
      },
    },
  ],
}

现在我仅使用idtitle的样本类型,但即使在这里,我仍然停留在如何正确映射它们的位置上,以便TS不会抱怨:(

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>
        },
      )}
    </>
  )
}

1 个答案:

答案 0 :(得分:1)

此问题与TS本身无关,因为错误是由于map回调的参数列表中的对象分解引起的。

当您将对象分解应用于函数的参数时,JS / TS会将对象的属性分配给具有相同名称的不同变量(除非它们是对象并且它们以相似的方式被分解)。

让我们看一下author属性的构造:

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

此代码段将按以下方式处理:

author.name属性将分配给不同的name变量。但是,

author.img不会被分配给不同的img变量,因为它是一个对象并且已解构。 它的属性将分别分配给不同的变量srcalt

此后,我们破坏了另一个属性:

    image: { src, alt },

同样,image将不会分配给不同的变量,因为它的对象已被解构。但这应该是属性。

它的属性是srcalt。并且应该将它们设置为具有这些名称的变量,但是我们已经有那些名称来自解构author.img

因此,变量定义中存在名称冲突,这就是TS编译器引发错误的原因。

您可以通过将属性分配给新变量名称来解决此问题,例如,通过以下方式:

({
          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
        }

在这里,我们为具有不同名称的变量显式分配了author.img属性,因此不再存在名称冲突。

解构分配技术可能确实有用,MDN上有更多示例

此后,您可能首先发现甚至不需要map,因为您在此处使用了数组解构:

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

然后,您可以直接访问其内部:

const {img} = data.data.author;

因此,您可能要删除.map(并直接渲染数据库条目)或不使用data变量初始化中的数组解构:

const data = useState([db]);