Search code examples
javascriptreactjsclassecmascript-6ecmascript-2016

How can I instantiate an object based on a string value


I have a string that I want to use in an API factory to instantiate the correct object from a class. Here is the code:

import StoryApiService from './story'
import AssignmentApiService from './assignment'

let apiTypes = {
    story: null,
    assignment: null
}
let token

const getApi = (newToken, apiType = 'story') => {
    const isNewToken = newToken => newToken !== token
    const shouldCreateService = !apiTypes[apiType] || isNewToken

    if( shouldCreateService ) {
        const capitalizedServiceType = apiType.charAt(0).toUpperCase() + apiType.slice(1)

        // this line is what I need help with
        apiTypes[apiType] = new `${capitalizedServiceType}ApiService`(token)
    }
    return apiTypes[apiType]
}

So basically depending on the apiType argument that is passed in I want to instantiate a new object from the correct class. I want to avoid using if/else and switch statements if possible because I have a bunch of different apiServices that I will use and I think this way will be cleaner if its possible.

I know the line in the code above won't work as written but its pseudo code to show the effect I want to achieve.


Solution

  • Rather than trying to instantiate a class from a string name (with some complex capitalization/concatenation logic), create an object that maps apiType names directly to their corresponding classes:

    import StoryApiService from './story'
    import AssignmentApiService from './assignment'
    
    const services = {
        story: StoryApiService,
        assignment: AssignmentApiService,
    }
    const serviceInstances = {
        story: null,
        assignment: null,
    }
    let token
    
    const getApi = (newToken, apiType = 'story') => {
        const isNewToken = newToken !== token
        const shouldCreateService = !serviceInstances[apiType] || isNewToken
    
        if (shouldCreateService) {
            token = newToken
            serviceInstances[apiType] = new services[apiType](token)
        }
        return serviceInstances[apiType]
    }