Let's assume that you've got a list of integrations, that you've stored in an enum:
enum IntegrationType {
CURRENCIES_API = 'CURRENCIES_API',
TIMEZONE_API = 'TIMEZONE_API',
PAYMENT_GATE = 'PAYMENT_GATE',
}
And you've got some API that returns only boolean info about available integrations:
{
CURRENCIES_API: true,
TIMEZONE_API: true,
PAYMENT_GATE: true,
}
You could, of course, write an interface for that response, using keys that you've declared before in enum.
interface IntegrationsResponse {
CURRENCIES_API: boolean;
TIMEZONE_API: boolean;
PAYMENT_GATE: boolean;
}
But they won't be connected. If something has changed in the enum or API response, you'll have to remember to update them in all places.
And what if you have much more integration types or some other, a more massive amount of data? If you want to store their keys in enum to use them somewhere else, you would have to add them to the enum, and the API response interface. Then, any change that will happen to any of them will cause you to recheck everything, to ensure that they're still matching each other.
There's a solution!
And it's pretty obvious, to be honest — you just need to use your enum keys in the interface. You can do it using the [key]
syntax:
const { CURRENCIES_API, TIMEZONE_API, PAYMENT_GATE } = IntegrationType;
interface IntegrationsResponse {
[CURRENCIES_API]: boolean;
[TIMEZONE_API]: boolean;
[PAYMENT_GATE]: boolean;
}
And that brilliantly does the job. But guess what — there's more. Instead of creating the interface using every key from enum, You can use all of your enum keys to creating a mapped type at once. You don't even need enum destructuring.
type IntegrationsResponse = {
[key in IntegrationType]: boolean;
}
Pretty neat, isn't it?
The usage is pretty simple :)
We're using such a solution in Evionica while fetching info about integration with some external services. Clean, safe, and easy-scalable solution. I hope, you find it useful.