0

I am trying to run a reduce on an array of objects but TypeScript says:

`Argument of type 'string' is not assignable to parameter of type 'never'`

I know it defaults to never because I need to declare the array of strings but I do not know where should I do it here

store.ts

// I have this data on a context provider

const data = [{
  Name: 'Peter',
  Dept: 'Finance'
},{
  Name: 'Jane',
  Dept: 'HR'
},{
  Name: 'Tom',
  Dept: 'HR'
}]
import { useMainContext } from './store'

function App = () {

  const { data } = useMainContext()
  const [departments, setDepartments] = useState<string[] | undefined>([])


  type Props = {
    Name: string,
    Dept: string
  }

  // I dont now where to include the props

  useEffect(() => {
    const depts = data.reduce((acc, current) => {
     if (!acc.includes(current.Dept))
      acc.push(current.Dept)
     return acc
    }, [])

    setDepartments(depts)
  }, [])
...
}
Álvaro
  • 2,255
  • 1
  • 22
  • 48
  • `const data: Props[] = ` – Roberto Zvjerković Mar 16 '21 at 13:07
  • But I not declaring data, I am getting it from context provider, I have edited the question – Álvaro Mar 16 '21 at 13:09
  • 3
    Not directly related, but the `reduce()` route can be improved upon. You can map and [pass through a set](https://stackoverflow.com/a/33121880/): `[...new Set( data.map(x => x.Dept) )]` – VLAZ Mar 16 '21 at 13:13
  • Why would that be an improvement, you first get the duplicates and then remove them, is it not better to only get them if the are not there already? – Álvaro Mar 16 '21 at 13:14
  • @VLAZ it turns out that this does not work on TypeScript, you need to enable `"downlevelIteration": true` on `tsconfig.json` and even then it adds a lot of boiler plate, what does work is `Array.from(new Set(data.map(({ Dept }) => Dept)))` but I am still unsure if this is more efficient. – Álvaro Mar 16 '21 at 13:35
  • 1
    @Álvaro it's `O(n)` as opposed to `O(n!)`. The set should have an `O(1)` lookup, so there is no need to do another `O(n)` lookup for *each* of the initial elements. – VLAZ Mar 16 '21 at 13:38
  • @VLAZ, thanks for the explanation, I have added this `Array.from(new Set(data.map(({ Dept }) => Dept )))` – Álvaro Mar 16 '21 at 13:40

1 Answers1

2

Just use Type Assertion for your initial value for .reduce()

const depts = data.reduce((acc, current) => {
 if (!acc.includes(current.Dept))
  acc.push(current.Dept)
 return acc
}, [] as string[]) //Added as string[]
Rajiv Punjabi
  • 486
  • 3
  • 6