1

Basically I'm trying to implement the equivalent of the C# LINQ ToDictionary() method in Typescript.

As an example, if I have a list of Person (with properties say int Id and string[] FirstNames), I would like to have as an output, a dictionary with Id as the key, and the FirstNames as the value.

What I currently did in Typescript:

interface IDictionary<T> {
    [index: string]: T;
}

Then I tried with map:

let result: IDictionary<string[]> = {}; 
let test = myObservable.map(b => b.map(item => result[item.moduleName] = item.jsFiles));

and with foreach

let test = myObservable.map(r => r.forEach(item => result[item.moduleName] = item.jsFiles));

Note that myObservable is of type Observable<Abc[]>

But it doesnt work... The goal would be to have in the test variable an Observable<IDictionary<string[]>>

Bidou
  • 7,378
  • 9
  • 47
  • 70

2 Answers2

1

Try this approach using reduce (DEMO):

interface IDictionary<T> {
    [index:string]: T
}

interface IObservable {
    Id: number,
    FirstNames: string[]
}


let myObservable: IObservable[] = [
    {
        Id: 0,
        FirstNames: ['John', 'Mary', 'Tom']
    },
    {
        Id: 1,
        FirstNames: ['Jack', 'Zak']
    }
];

let result: IDictionary<string[]> = myObservable.reduce((acc: IDictionary<string[]>, val: IObservable): IDictionary<string[]> => {
    acc[val.Id] = val.FirstNames;
    return acc;        
}, {});

console.log(result); // { 0: ["John","Mary","Tom"], 1: ["Jack","Zak"] }

EDIT

Try this (untested) according to Question

let observableResult: Observable<IDictionary<string[]>> = Observable.of(result);
kapantzak
  • 11,610
  • 4
  • 39
  • 61
  • I have the following error with this code: `TS2345: Argument of type '(acc: IDictionary, val: T) => IDictionary' is not assignable to parameter of type '(acc: {}, value: T[], index: number) => {}'. Types of parameters 'val' and 'value' are incompatible. Type 'T[]' is not assignable to type 'T'.` – Bidou Jan 15 '18 at 07:54
  • Okay, the problem is that I have an Observable array and not just an array as in your example... so basically, in your example, it would be a Observable. Not sure if this solution is working in this case? – Bidou Jan 15 '18 at 08:15
  • Not sure to understand your edit (sorry, I'm new to Typescript)?! My variable `myObservable` is of type `Observable`, so not sure when do I have to put then `Observable.of` ? – Bidou Jan 15 '18 at 08:26
1

After a lot of try and retry, I finally managed to have a working solution. I'm sharing it here, hopefully it will helps someone else in the future:

let result = myObservable.map(data => {
             return data.reduce((acc: IDictionary<string[]>, val: T): IDictionary<string[]> => {
                acc[val.moduleName] = val.jsFiles;
                return acc;
             }, initialValue);
        });

Thanks to @kapantzak which took me in the right direction.

Bidou
  • 7,378
  • 9
  • 47
  • 70