Reputation: 22837
We have a module that exports objects from other files.
For simplicity sake, let's call this Vehicle
. It exports Car
, Boat
, and Plane
.
We have an enum that corresponds to these vehicles, let's say the following:
enum Vehicles {
Car,
Boat,
Plane,
}
We are looking to use the enum to specify which imported object we should then use.
We're aware that we can do a switch/case, but this becomes unnecessarily long as our enum grows. Some of our classes export dozens of variations of objects that we then use elsewhere (we are unable to use types/interfaces to simplify).
switch(vehicle) {
case Vehicles.Car: {
return Car;
}
case Vehicles.Boat: {
return Boat;
}
case Vehicles.Plane: {
return Plane;
}
}
We are using TypeScript with Svelte. The import is a package (e.g. Google Charts [charts], fortawesome [icons], etc.). We are looking to create a sort of wrapper to easily initialize specific components.
Example:
<script lang="ts">
import { a, b, c } from x
const y = () => {
// logic here
}
</script>
<y/>
This question seems to be TypeScript-specific, so I've purposely left out svelte tag from my question
Upvotes: 7
Views: 841
Reputation: 1061
My solution is largely inspired by blaumeise20.
Note: React is just used as an example here. Your imports can be anything
Heres what I came up with:
import { Component, useCallback, useEffect } from 'react';
const imports = { Component, useCallback, useEffect } as const;
function getCorrectImport<K extends keyof typeof imports>(key: K): typeof imports[K] {
return imports[key];
}
You can then call this function like this:
getCorrectImport('Component'); // You should get completion hints and correct typings using this
The Downside is you will need to stuff your imports into an object like I created the imports
object.
A cool way if you import everything from a module could be something like this:
import * as React from 'react';
function getCorrectImport<K extends keyof typeof React>(key: K): typeof React[K] {
return React[key];
}
const correctObject = getCorrectImport('Component');
This can allow you to not create an object but the downside would be you would need to import everything from the module you are importing from. This works because the * as React
syntax creates an object for you.
If you can do that, this would be an ideal solution.
Upvotes: 0
Reputation: 684
Why can't you use this one?
enum Vehicle {
Car= 'CAR',
Boat= 'BOAT',
Plane= 'PLANE',
}
Regards, N Baua
Upvotes: -1
Reputation: 2220
So I tried some things, here you can see them:
I tried to assign the classes to the enum properties, but it didn't work. How I imagined it is like this:
enum Vehicle {
Car = Car,
Boat = Boat,
Plane = Plane,
}
But TypeScript gives me an error. You can try it here. Why did I think about that? Because you can assign value to enum properties like this:
enum Char {
A = 65,
B = 66,
C = 67,
D = 68,
// ...
}
But as you can see, it doesn't work in your case.
You could just forget using an enum. There is a special feature in TypeScript, as const
. It makes an array or object literal constant. That would look somehow like this:
const Vehicle = {
Car,
Boat,
Plane
} as const;
Why don't I use a value? That is called property shorting (or something like that). When you have a variable or some named thing and want to use it with the same property name, you don't have to specify one. Here is the example using the as const
version.
You can use Object.keys
to get an array of keys. It look somehow like this:
const index = 1;
const keys = Object.keys(Vehicle);
const vehicle = Vehicle[keys[index]];
I'm not going to add a link here because it is not really important.
Upvotes: 3
Reputation: 421
You can use a map of
const vehicleComponentsMap: Record<Vehice, SvelteComponent> = {
[Vehicle.Car]: Car,
....
}
And then if you have a convention for the Vehicle implementation files, you can use it to dynamically build this map (by collecting data from files by convention).
Upvotes: 0