Reputation: 2128
How do I get rid of this error at config[curr][targetEnv]
???
interface EnvType {
dev: string;
staging: string;
production: string;
}
type Config = {
[key: string]: number | string | EnvType;
};
const config: Config = {
networkTimeout: 10000,
apiHost: {
dev: 'http://localhost:8080',
staging: 'https://staging.example.com',
production: 'https://example.com',
},
};
const targetEnv = process.env.TARGET_ENV || 'dev';
const mappedConfig = Object.keys(config).reduce((acc, curr) => {
const currValue = config[curr];
// string or number or boolean; just return the value
if (typeof currValue !== 'object') {
return { ...acc, [curr]: currValue };
}
// is object; retrieve value by env
if (typeof currValue === 'object') {
return { ...acc, [curr]: config[curr][targetEnv] }; // error on this line
}
// do nothing
return { ...acc };
}, {});
export default mappedConfig;
Upvotes: 0
Views: 125
Reputation: 26727
First you have to constrain your process.env.TARGET_ENV
, to ensure that value can be only dev
, staging
or production
:
const targetEnv = (process.env.TARGET_ENV as keyof EnvType) || 'dev';
Secondly, cast config[curr] as EnvType
inside of typeof currValue === 'object'
condition. That way you tell to TypeScript that you're sure that config[curr]
returns correct EnvType
, and not string
or number
when if
condition is met.
// is object; retrieve value by env
if (typeof currValue === 'object') {
return { ...acc, [curr]: (config[curr] as EnvType)[targetEnv] }; // error on this line
}
Full example would be:
interface EnvType {
dev: string;
staging: string;
production: string;
}
type Config = {
[key: string]: number | string | EnvType;
};
const config: Config = {
networkTimeout: 10000,
apiHost: {
dev: 'http://localhost:8080',
staging: 'https://staging.example.com',
production: 'https://example.com',
},
};
const targetEnv = process.env.TARGET_ENV as keyof EnvType || 'dev'; // added `as keyof`
const mappedConfig = Object.keys(config).reduce((acc, curr) => {
const currValue = config[curr];
// string or number or boolean; just return the value
if (typeof currValue !== 'object') {
return { ...acc, [curr]: currValue };
}
// is object; retrieve value by env
if (typeof currValue === 'object') {
return { ...acc, [curr]: (config[curr] as EnvType)[targetEnv] }; // added `as`
}
// do nothing
return { ...acc };
}, {});
export default mappedConfig;
Upvotes: 1
Reputation: 5570
You're trying to look up a value using a string key. It will work for config[curr]
because of this line in your config type type:
[key: string]: number | string | EnvType;
But then you're trying to do the same thing in your object of EnvType
.
You need to do the same thing for that interface like so:
interface EnvType {
[key: string]: string;
dev: string;
staging: string;
production: string;
}
After that the problem will likely become that config can be a number
or a string
, both of which can't be indexed like that.
Upvotes: 0