What is the typescript syntax for keyed arrays

374 views Asked by At

I don't actually know what to call the argument to merge in the second line below, but it looks like an array of objects that have a string key. What is the argument called in English, and how do I construct/pass the ...iterables: {[key: string]: V}[]

merge(...iterables: Iterable<K, V>[]): Map<K, V>
merge(...iterables: {[key: string]: V}[]): Map<string, V> // THIS ONE! what?!

The source comes from the ImmutableJS merge documentation.

merge() Returns a new Map resulting from merging the provided Iterables (or JS objects) into this Map. In other words, this takes each entry of each iterable and sets it on this Map.

DISCUSSION If any of the values provided to merge are not Iterable (would return false for Immutable.Iterable.isIterable) then they are deeply converted via Immutable.fromJS before being merged. However, if the value is an Iterable but includes non-iterable JS objects or arrays, those nested values will be preserved.

I understand the first one, but What is going on in the second one? This is my best guess (es6 syntax):

const iterable1 = fromJS([{"other":"b"}])
const merged = fromJS({"self":"a"}).merge(iterable1, iterable ...)

Edit:

After reading the answer, I was confusing (a number of things, but mainly) es6 syntax with typescript syntax. The answer below treats Rest Parameters quite nicely to help with the distinction.

1

There are 1 answers

2
Nitzan Tomer On BEST ANSWER

That is called Indexable Types in typescript:

Indexable types have an index signature that describes the types we can use to index into the object, along with the corresponding return types when indexing

For example:

let obj: { [name: string]: number };
obj = { a: 1, b: 2 }; // ok
obj = { a: "1" }; // error: Type '{ a: string; }' is not assignable to type '{ [name: string]: number; }'

In the case of the immutable signature:

merge(...iterables: {[key: string]: V}[]): Map<string, V>

It means:

fromJS({ "key1": "str1" }).merge({ "key2": "str2" }, { "key3": "str3" }, ...);

The V generic constraint is infered to be string because of the value in the object that is the parameter for fromJS, then the rest of the objects need to be string => string as well.


Edit

In your example there's no use of the spread operator, what's in use is called Rest Parameters:

function fn<T>(...args: T[]) {
    args.forEach(item => console.log(item));
}

Compiles to:

function fn() {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    args.forEach(function (item) { return console.log(item); });
}

And can be used like so:

fn();
fn(1);
fn(1, 2, 3);
fn("str1", "str2");
fn(1, "str"); // error: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly