Get an object key by its value with TypeScript
Let's take a look at how we can get the key of a JavaScript object by its value. It's essentially a reverse lookup on the object in order to get the object key for a certain object value.
Getting a key by its value
Let's say we have a Podium
object with a mapping of podium placement strings to numeric representations.
To find the Podium
key that corresponds to a certain Podium
value, we can loop over the keys of Podium
and do an equality check on each key's value.
const Podium = {
first: 1,
second: 2,
third: 3,
};
// TypeScript ERROR for `Podium[key]`
const key = Object.keys(Podium).find((key) => Podium[key] === 3);
console.log(key);
The Podium[key]
reference in the code above results in the following TypeScript error:
Element implicitly has an 'any' type because expression
of type 'string' can't be used to index type
'{ first: number; second: number; third: number; }'. No
index signature with a parameter of type 'string' was found...
What does this error mean? It means that TypeScript is unable to index or reference the object Podium
by using a key with a string value, such as "first"
. The reason for this is because we didn't provide TypeScript with the exact type structure of our Podium
object.
We should tell TypeScript the exact properties and data types that make up Podium
object.
Typing the object
const Podium: { [key: string]: number } = {
first: 1,
second: 2,
third: 3,
};
const key = Object.keys(Podium).find((key) => Podium[key] === 3);
console.log(key); // "third"
By defining Podium
with the type { [key: string]: number }
, the initial TypeScript error is gone. The key "third"
for the lookup that uses the value of 3
is now printed to the console.
keyof typeof operators
Rather than providing an explicit type for Podium
, another solution is to use the TypeScript keyof
operator and the JavaScript typeof
operator.
const Podium = {
first: 1,
second: 2,
third: 3,
};
const key = Object.keys(Podium).find(key => Podium[key as keyof typeof Podium] === 3);
console.log(key); // "third"
The Podium[key]
reference now becomes Podium[key as keyof typeof Podium]
. The TypeScript error is resolved and the key "third"
is printed to the console.
The JavaScript typeof
operator retrieves the type of a variable or property.
console.log(typeof Podium); // object
The keyof
operator receives an object type and produces a literal union of all the keys that make up that object. Since keyof
must receive an object type, we had to provide it with typeof Podium
to produce the valid keyof
expression keyof typeof Podium
.
Here's an example to demonstrate how keyof
works.
type PodiumKeyType = keyof typeof Podium;
let runner: PodiumKeyType;
runner = "first";
runner = "second";
runner = "third";
// TypeScript ERROR
// Type '"fourth"' is not assignable to type '"first" | "second" | "third"'
runner = "fourth";
The type PodiumKeyType
that we created above is the literal union type of "first" | "second" | "third"
. Thus, the runner
variable that we declare to be of type PodiumKeyType
can only be assigned the string values that make up that literal union type.
Conclusion
To get an object key by it's value in TypeScript, we can use either one of the approaches that we saw above.
- Define the type of the object when we create it, or
- Use the
keyof
andtypeof
operators when retrieving the object value by its key.