Is there a better method than the following for looping through the keys of an object and return a new object with the same key but the values transformed and ensuring the resulting type contains that same keys as the input.
const env = {
KEY_1: "VALUE_1",
KEY_2: "ANOTHER_VALUE_2"
};
function mapValuesToLength<TEnv extends Record<string, string>>(
env: TEnv
): Record<keyof TEnv, number> {
const result: Partial<Record<keyof TEnv, number>> = {};
for (const envKey in env) {
result[envKey] = env[envKey].length;
}
return result as Record<keyof TEnv, number>;
}
// expecting result = {KEY_1: 7, KEY_2: 15}
const result = mapValuesToLength(env);
// expecting type resultType = { KEY_1: number; KEY_2: number; }
type resultType = typeof result
How about the following approach (single line):
const env = {
KEY_1: "VALUE_1",
KEY_2: "ANOTHER_VALUE_2"
};
type InputType = Record<string, string>;
type OutputType<T> = Record<keyof T, number>;
function mapValuesToLength<TEnv extends InputType>(env: TEnv): OutputType<TEnv> {
return Object
.entries(env)
.reduce((acc, [key, value]) => ({ ...acc, [key]: value.length }), {} as OutputType<TEnv>);
}
const result = mapValuesToLength(env);
console.log(result);
Steps:
Object.entries(): returns an array of a given object's own enumerable string-keyed property [key, value] pairs.Array.prototype.reduce(): executes a reducer function on each element of the array.
({ ...acc, [key]: value.length }): returns the current accumulator (result object) with the new element (current) key: value(length).{} as OutputType<TEnv>: initilialize the accumulator as an empty object having the correct output type.Typescript Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With