Prozak
Prozak

Reputation: 303

Argument of type 'any' is not assignable to type 'never'

I am fetching images from an endpoint and having trouble pushing each mapped file into my local array. I am receiving the error Argument of type 'any' is not assignable to type 'never'.

import * as React from "react"
import { Company } from "data/companies"
import { Asset } from "data/companies"

interface MediaLibraryProps {
  company: Company
}

class MediaLibrary extends React.Component<MediaLibraryProps> {
  state = {
    mediaLibrary: []
  }

  getMediaLibrary = async () => {
    await fetch(
      `${process.env.REACT_APP_SA_API_URL}/${this.props.company.id}/medialibrary`,
    ).then(blob => blob.json())
      .then(function (data) {
        return data.map((file: Asset) => {
          return {
            id: file.assetId,
            path: file.path
          }
        })
      }).then(data => this.state.mediaLibrary.push(...data))
  }

  public render() {
    const files = this.state.mediaLibrary.map((file: Asset) => (
      <div key={file.assetId}>
        <div>
          <img src={`url(${process.env.REACT_APP_SA_CDN_URL}${file.path})`} />
        </div>
      </div>
    ))

    return (
      <div>
        <div>
          <h2>Media Library</h2>
          {files}
          <button onClick={this.getMediaLibrary}>Get Files</button>
        </div>
      </div>
    )
  }
}

export default MediaLibrary

IMPORTANT: After solving this issue I found my problem was not with the state. Although the solution allows me to push objects into the array I was mutating the state directly which is a nono in React. See below:

class MediaLibrary extends React.Component<MediaLibraryProps> {
  state = {
    mediaLibrary: []
  }

  getMediaLibrary = async () => {
    await fetch(
      `${process.env.REACT_APP_SA_API_URL}/${this.props.company.id}/medialibrary`
      }
    ).then(blob => blob.json())
      .then(function (data: any) {
        return data.map((file: Asset) => Object.assign(file, {
          assetId: file.assetId,
          path: file.path
        }))
      }).then((data) => this.setState({ mediaLibrary: [...data] }))
  }

Upvotes: 9

Views: 28171

Answers (1)

Bj&#246;rn Hei&#223;
Bj&#246;rn Hei&#223;

Reputation: 1728

You should declarate your mediaLibrary array like this:

state = {
  mediaLibrary: Array<{id: string, path: string}>()
}

or like this:

state: {
  mediaLibrary: {id: string, path: string}[]
} = {
  mediaLibrary: []
}

With the first way you're telling TypeScript you want to put objects with the given attributes inside the mediaLibrary array. With just [] TypeScript will put the never type to the array and hence fails to put anything into it.

The second example describes the complete state object and not just the included array.

Upvotes: 17

Related Questions