0

I'm trying to map object with keys so that I can easily return them. I can either get a string or RegExp which is the problem, setting the key as a string is easy.

This is how I set key for object when route is string, but the problem is that I cannot set regex as a key, it needs to be either a number or a string.

private nodesByRoute: { [key: string]: NavbarItemNode } = {};

this.nodesByRoute[node.route] = node;

So I would imagine the solution would look something like this:

private nodesByRoute: { [key: string | RegExp]: NavbarItemNode } = {};

My implementation is that I get a route string, let's say /category/items and if it matches it will return the node like this:

return this.nodesByRoute[routerLink];

But I also need this to work with regex because I can get something like this: /items/60. So I get items/ and the number of the item, thats why I need regex as a key.

Also I think I will also need logic when trying match the keys with my route. The route will always be a string but the key might be regex so I don't think this will work:

return this.nodesByRoute[routerLink];
C0mpl3x
  • 480
  • 4
  • 21
  • I don't think that this is possible because JavaScript only allows for keys of type `string`: https://stackoverflow.com/questions/3608246/what-is-the-type-of-keys-in-javascript – Ogod Jun 11 '21 at 13:14

1 Answers1

1

Not sure what you want in your case.

But if you want to use something as a key besides string and number, you can try Map.

const nodesByRoute: Map<RegExp, NavbarItemNode> = new Map<RegExp, NavbarItemNode>();

However, there is a caveat. If you use a literal RegExp to get the value, it will not work.

const m = new Map<RegExp, string>();
m.set(/ab.*/, "Hello World");
console.log(m.get(/ab.*/)); // undefined

Because the different literal RegExp will be treated as different RegExp instances, using a non-primitive object as a key of a Map means using the object's reference as a key. So the code below will work.

const m = new Map<RegExp, string>();
const regexKey: RegExp = /ab.*/;
m.set(regexKey, "Hello World");
console.log(m.get(regexKey)); // "Hello World"

When you are trying to do so, it also means you need to manage all of those RegExp keys. That may not be what you want to take the time to do.

And I think the thing you really want to is such like:

const m = new Map<RegExp, string>();
m.set(/ab.*/, "Hello World");
console.log(m.get('abc')); // undefined

Again, the string 'abc' will not automatically match the RegExp key. That's the part you need to do some work.

In my opinion, you can try to create a method that implements the logic of different route patterns checking, then return the value you want with easily call the method as below:

let node = this.nodesByRoute(routerLink);
Chris Kao
  • 410
  • 4
  • 12
  • Thank you, yes my plan is for it work like the last solution you gave, so I guess I'll need to play with the logic a bit when returning the value. – C0mpl3x Jun 14 '21 at 10:16