0

I want to convert my typescript object keys to upper case, I want to know a good way to turn this?

var obj = {key1: value1,key2: value2}; into:

var obj = {KEY1: value1,KEY2: value2};

Can anyone suggest a better method without multiple looping and all?

2

3 Answers 3

0
x = {}
Object.entries(obj).forEach(([k, v]) => {x[k.toUpperCase()] = v})
obj = x
Sign up to request clarification or add additional context in comments.

1 Comment

This will still not have impact on types, because key signature of x still wil be a plain string.
0

The most complicated part of this would be the typesafety as the Javascript is pretty straight forward.

All we need to do is isolate the keys/types we need to build out the "uppercased" copy of the object.

// All string-type keys in the object, and then uppercased
type UppercaseStringKeys<T> = Uppercase<Extract<keyof T, string>>;
// All non-string-type keys in the object type T
type NonStringKeys<T> = Exclude<keyof T, string>;
// Union of the above types
type NonStringAndUppercaseStringKeys<T> = NonStringKeys<T> | UppercaseStringKeys<T>;
// An object consisting of the above keys with the same values from the original object
type UppercaseObjectKeys<T extends { [key: string | number | symbol]: any }> = {
    [x in UppercaseStringKeys<T>]: x extends string ? T[Lowercase<x>] : T[x];
};

We can obviously make this shorter - the above is purely for readability

type UppercaseObjectKeys<T extends { [key: string | number | symbol]: any }> = {
    [x in Uppercase<Extract<keyof T, string>> |  Exclude<keyof T, string>]: x extends string ? T[Lowercase<x>] : T[x];
};

Now all we need to do is do the Typescript mapping.

function uppercaseObjectKeys<T extends Record<any, any>>(existingObject: T) {
    return Object.keys(existingObject).reduce((acc,key) => {
        const newKey = `${key}`.toUpperCase() as keyof UppercaseObjectKeys<T>;
        acc[newKey] = existingObject[key];
        return acc;
    }, {} as UppercaseObjectKeys<T>);
}

That's also fairly straight forward, we just return a new object with the "uppercased" keys.

We could edit the original object, but that's not the crux of this questions.

Then using the above function is straight forward, it should return us the new object with all string-type keys uppercased.

const x = {
  foo: {},
  bar: 1,
  bazz_bazz: 'some string',
  1: 2,
};
const y = uppercaseObjectKeys(x);
console.log(x);
/** {
  "1": 2,
  "foo": {},
  "bar": 1,
  "bazz_bazz": "some string"
} */
console.log(y);
/** {
  "1": 2,
  "FOO": {},
  "BAR": 1,
  "BAZZ_BAZZ": "some string"
} */
// works
y[1];
// wont work
y[2];

2 Comments

Excellent approach, what if I need to set uppercase on the values not the keys? I need to set to uppercase all type==="string" values in the object.
We would have to adjust UppercaseObjectKeys slightly - there are a number of questions I would have to ask though. So it would probably be better off as a separate question.
0

Assuming you have:

const obj1 = { key1: '', key2: '' };

You can do:

import { ValueOf } from "type-fest";

const uppercasedObj1 = Object.fromEntries(
  Object.entries(obj1).map(
    ([value, key]) => [value.toUpperCase(), key]
  )
) as Record<Uppercase<keyof typeof obj1>, ValueOf<typeof obj1>>;

Explanation: Some kind of looping is needed, you can't avoid this. In this case we used Object.entries() and Object.fromEntries() to declaratively loop through object properties - not the most optimal way, but quite declarative and relatively easy to write.

As for make it work for TypeScript, we need to cast the type after looping, because index signature of looped object would be always string. Here we used built-in Uppercase type to transform keys and ValueOf from TypeFest library (just to not litter the example with typing value of object).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.