The approach described in the Paul's answer is correct, however there is one detail I missed which I like to add: How do you specify genId
correctly, so it works for both collections?
The answer is referring to the "Heroes" example written in TypeScript (a superset of JavaScript), specifically the HTTP chapter.
There, a table heroes
is simulated by implementing:
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const heroes = [
{ id: 11, name: 'Mr. Nice' },
{ id: 12, name: 'Narco' },
// ...
{ id: 20, name: 'Tornado' }
];
return {heroes};
}
// Overrides the genId method to ensure that a hero always has an id.
// If the heroes array is empty,
// the method below returns the initial number (11).
// if the heroes array is not empty, the method below returns the highest
// hero id + 1.
genId(heroes: Hero[]): number {
return heroes.length > 0 ? Math.max(...heroes.map(hero => hero.id)) + 1 : 11;
}
}
Now, if you add a 2nd collection crises
as shown in his answer, i.e.:
createDb() {
let heroes = [ { ... }, ... ];
let crises = [ { ... }, ... ];
return { heroes, crises };
// or { heroes: heroes, crises: crises }
}
how do you provide genId
for both collections (provided they are of type Hero
and Crises
)? Overloading, as you would do it in C#
does not work in TypeScript, it would throw an error ("Duplicate function implementation").
Solution:
I found out, that you can solve this issue with TypeScript's Generics as follows. Replace the otiginal genId
function by the following generic version:
genId<T extends Hero | Crises>(myTable: T[]): number {
return myTable.length > 0 ? Math.max(...myTable.map(t => t.id)) + 1 : 11;
}
What's important here is the part <T extends Hero | Crises>
: It means that type T
can be either Hero
or Crises
: So it will be invoked if the parameter passed is either of type Hero[]
or Crises[]
.
With that knowledge, adding a 3rd, 4th, ... class is simple: Just append the class. Say we want to add the class SuperHero
, then you just append it via | SuperHero
, so it would look like:
genId<T extends Hero | Crises | SuperHero>(myTable: T[]): number {
return myTable.length > 0 ? Math.max(...myTable.map(t => t.id)) + 1 : 11;
}
Note: As a prerequisite, all classes (Hero
, Crises
and SuperHero
) need to have a numeric id
property declared.
Useful links: