1

I'm in the process of optimizing some code in my library, however, I have a bit of an issue regarding why bracket notation isn't working when trying to call an imported class.

Parameter type accepts a string that is camelCased, such as: myString. The parameter data can be anything.

import { foo } from './example';

export const find = (type: string, data: any) => {

// This next line effectively deletes the end of the string starting
// from the first capital letter.
    const f = type.replace(/[A-Z][a-z]+/, '');
    try {
        return [f][type](data);
    } catch (e) {
        return e;
    }
};

this is what I expect it to look like if I was to visualize it using dot notation:

foo.fooBar(someRandomData)

This should call the static method fooBar(data) on the imported class foo, however, I receive an error message:

TypeError: [f][type] is not a function

If I was to revert it back to my if..else if style, it works:

if (type.startsWith('foo')) return foo[type](data);

How can I do what is desired above without getting the defined error message?

Thank you for your help in advance!

EDIT: This is an example I modified from already existing code, therefore, I fixed a few typos.

EDIT #2: as per requested, the imported class foo looks like this:

export class foo{
static fooBar(data){
// Do stuff with data...
}
7
  • This is unclear to me. What are you trying to accomplish with the [f][type] syntax? Because what you're doing is creating an array containing f, then trying to access the property named type from said array, which is probably returning undefined, which is not a function. Commented Jun 5, 2019 at 0:50
  • First, you should probably not use "type" like this, considering it is a keyword. Second, type is a string, and you are trying to use it like an array of functions. Third, I don't see any reference to foo. How does foo relate to your code above? Could you also include the code for foo (the "example" file)? Commented Jun 5, 2019 at 0:52
  • Are you trying to say that if your type string is, for instance 'fooBar', then it should call foo.bar(data)? Commented Jun 5, 2019 at 0:56
  • the end goal is to access the correct imported class (because there's more than one class, but not in this example) so that is why I have it structured like [class][method](data) so I can dynamically call the correct class without having to do a bunch of if statements. Unless this isn't possible and I'm missing something..? Commented Jun 5, 2019 at 1:02
  • Here is a post about exporting a static class - from your code sample I don't see anything wrong with what you did: stackoverflow.com/questions/16207593/…. Commented Jun 5, 2019 at 1:08

2 Answers 2

0

In the end you need some reference to the classes or object to get started with. Here is a working example of how you could do this type of functionality, but you have start with a map of your class instances so you can get to them:

class foo {
    fooBar(data: any) { return { name: 'foo', data } };
}

class example {
    exampleFood(data: any) { return { name: 'example', data } };
}

var lookup: { [classes: string]: any; } = { };
lookup['foo'] = new foo();
lookup['example'] = new example();

const find = (encodedType: string, data: any) => {
    // This next line effectively deletes the end of the string starting
    // from the first capital letter.
    const f = encodedType.replace(/[A-Z][a-z]+/, '');
    try {

        return lookup[f][encodedType](data);
    } catch (e) {
        return e;
    }
};

alert(JSON.stringify(find("fooBar", "Found you foo")));
alert(JSON.stringify(find("exampleFood", "Found you example")));
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this is a much better option than using conditional statements as what you did was key/value the classes in lookup. I will be using a slightly modified version, so I thank you for this!
0

I would suggest you instead move over to using the nodeJS built-in EventEmitter.

You can do something like:

import * as EventEmitter from 'events';

import { foo } from './example';
import { bar } from './example2';

export const discordEventEmitter = new EventEmitter();

discordEventEmitter.on('fooBar', foo.fooBar);
discordEventEmitter.on('fooToo', foo.fooToo);
discordEventEmitter.on('barBell', bar.barBell);

Then, when you want to fire an event, you can simply:

discordEventEmitter.emit('fooBar', someData);

You can also simplify the event handler registration by writing:

const fooProps = Object.getOwnPropertyNames(foo) as (keyof typeof foo)[];
fooProps.filter(k => typeof foo[k] === 'function').forEach(funcName => {
  discordEventEmitter.on(funcName, foo[funcName]);
});

const barProps = Object.getOwnPropertyNames(bar) as (keyof typeof bar)[];
fooProps.filter(k => typeof bar[k] === 'function').forEach(funcName => {
  discordEventEmitter.on(funcName, bar[funcName]);
});

Comments

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.