Definitelytyped: [@types/lodash] Property 'map' does not exist on type FunctionChain<any>

Created on 21 May 2019  路  8Comments  路  Source: DefinitelyTyped/DefinitelyTyped

  • [x] I tried using the @types/xxxx package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @aj-r @sandersn

One more similar to https://github.com/DefinitelyTyped/DefinitelyTyped/issues/35400 issue (ts is in strick mode):

chain([1, 2, 3, 4, 5])
  .reduce((acc: any, x) => {
    acc[x] = x
    return acc
  }, {})
  .map(x => x * 2)
  .value()

with @types/lodash 4.14.121 it works fine, but with 4.14.126 I get a type error:

 Property 'map' does not exist on type 'FunctionChain<any> | ObjectChain<any> | PrimitiveChain<any> | StringChain | (CollectionChain<any> & FunctionChain<any> & ObjectChain<any> & PrimitiveChain<any> & StringChain) | StringNullableChain | CollectionChain<...>'.
  Property 'map' does not exist on type 'FunctionChain<any>'.

Obviously map function is exist here in any case and this is incorrect error.

Update: Same issue happens with mapValues after reduce too

Most helpful comment

where you guys able to figured out this issue?

All 8 comments

I think the types are having trouble with the acc: any part. It might be possible to fix but I'm not sure.

You can probably give a stricter type than any, e.g. (acc: { [key: string]: any }, x) => .... That should fix the error, and has the added benefit of being more type-safe.

@aj-r, you're right it will work as expected with more strict type:

interface MyInterface { [key: string]: any }

chain([1, 2, 3, 4, 5])
  .reduce((acc: MyInterface, x) => {
    acc[x] = x
    return acc
  }, {} as MyInterface)
  .map(x => x * 2)
  .value()

But error

 Property 'map' does not exist on type 'FunctionChain<any> | ObjectChain<any> | PrimitiveChain<any> | StringChain | (CollectionChain<any> & FunctionChain<any> & ObjectChain<any> & PrimitiveChain<any> & StringChain) | StringNullableChain | CollectionChain<...>'.
  Property 'map' does not exist on type 'FunctionChain<any>'.

still doesn't make any sense. In case of acc: any you still have property map on your FunctionChain<any>. At least this is incorrect error message.

The problem is that reduce returns acc, and when acc: any, it can't guarantee that it does have the map method. It might be a function, for example, which doesn't have map. You should either add a type to acc or not put a type annotation at all (which is a noImplicitAny error, but fine without strict on).

You're right acc might be a string, number or function, but map always exists at Chain<any>:

const { chain } = require('lodash')

const fn = chain([1, 2, 3, 4, 5])
  .reduce(() => () => {})

const num = chain([1, 2, 3, 4, 5])
  .reduce(() => 42)

const str = chain([1, 2, 3, 4, 5])
  .reduce(() => 'string')


console.log(fn.map) // [Function]
console.log(num.map) // [Function]
console.log(str.map) // [Function]

So maybe semantically this error make sense, but this error get wrong information to end users.

Edit: Moreover any type means that any.map is exist or at least missing of this property is not an error from types point of view.

@aj-r @sandersn, any updates about that? If my points are not enough here, so here is 1 more unsolvable point:

interface Token {
  [key: string]: any
}

chain(decodedToken as Token).get('[cognito:groups]').map(decodeGroup).orderBy().value()

```
Property 'map' does not exist on type 'FunctionChain | ObjectChain | PrimitiveChain | StringChain | (CollectionChain & FunctionChain & ObjectChain & PrimitiveChain & StringChain) | StringNullableChain | CollectionChain<...>'.
Property 'map' does not exist on type 'FunctionChain'.

There is no any way to fix that, except ugly any-wrapper:
```tsx
(chain(decodedToken as Token).get('[cognito:groups]') as any).map(decodeGroup).orderBy().value()

map, mapValues and get should exist at ObjectChain<any> | PrimitiveChain<any>. Otherwise meaning of any has no any sense here.

I use the lodash(4.17.11) and the different @types/lodash(4.14.118 and 4.14.136), the 4.14.118 is worked, but the 4.14.136 is showing the error.

It is still happening with v4.14.149

where you guys able to figured out this issue?

Was this page helpful?
0 / 5 - 0 ratings