5

I'm looking at facebook's immutable library and their typescript bindings.

If I have this code:

const list: User[] = ...;
list.map(user => ...)

The type of the lambda parameter user is correctly User.

However, if I import immutable's List and wrap my array:

import {Map, List} from "immutable";
List(list).map(user => ...)

Now, and it's baffling to me, the lambda parameter user is inferred to be User | undefined. Even changing the call to List<User>(list) does not help.

Looking at the .d.ts for the library, the definition is:

export function List<T>(array: Array<T>): List<T>;

So I don't understand what is going on here?

2
  • Are you using strict null check? Commented Dec 9, 2016 at 23:07
  • yes, strict null checks and also no implicit any. Commented Dec 9, 2016 at 23:09

1 Answer 1

4

The reason for this is written in the What's new in TypeScript 2.0 in the Optional parameters and properties part:

Optional parameters and properties automatically have undefined added to their types, even when their type annotations don't specifically include undefined. For example, the following two types are identical:

// Compiled with --strictNullChecks
type T1 = (x?: number) => string;              // x has type number | undefined
type T2 = (x?: number | undefined) => string;  // x has type number | undefined

Edit

The definition file for immutable.js changed, now if you look at the signature of the map method it looks like this:

map<M>(
    mapper: (value: V, key: K, iter: /*this*/Iterable<K, V>) => M,
    context?: any
): /*this*/Iterable<K, M>;

But if you go a commit before that it looks like this:

map<M>(
    mapper: (value?: V, key?: K, iter?: /*this*/Iterable<K, V>) => M,
    context?: any
): /*this*/Iterable<K, M>;

And here the value is optional.

If you update the definition file it will be fixed.

Sign up to request clarification or add additional context in comments.

7 Comments

i don't think the first parameter of the map callback is optional. The signature is this one or similar I think => map<M>(mapper: (value: V, key: K, iter: this) => M,context?: any): /*this*/Iterable<K, M>;
I really have that old definition on my disk it seems! Although I just installed it. I installed through npm install @types/immutable --save and got "@types/immutable": "3.8.6". Is there a better way?
(I also have issues with the tsmonad type definition which seems to conflict with node over the variable 'module'. I thought installing type definitions through npm & @types was the right way now?
The file in @types/immutable is the latest one (with the params as not optional), but the immutable.js library comes with its' own .d.ts file and the compiler might be using that instead of the @types/immutable. Check what you have there, maybe you need to update your immutable.js lib.
i have "immutable": "3.8.1" in my package.json, seems to be the latest :(
|

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.