Is there a `valueof` similar to `keyof` in TypeScript? Optimization and performance
\n\nHave you ever written TypeScript and caught yourself thinking: "I have keyof for keys, but where is valueof for values?" If so — you are not alone. This question on Stack Overflow has gathered thousands of views, and today we will break it down from start to finish. But not just as abstract theory, but with a focus on optimization and performance of your code. Let's go!
Why does `keyof` exist, but `valueof` does not?
\n\nTypeScript has a built-in utility type keyof. It takes an object type and returns a union of all its keys:
type Person = {\n name: string;\n age: number;\n isActive: boolean;\n};\n\ntype PersonKeys = keyof Person; // "name" | "age" | "isActive"\n\nWhat about values? You want to get string | number | boolean from the same type. There is no such thing in the TypeScript standard library. Why? Because valueof is not just a "reverse operation". An object can have many keys with the same types, and we need to decide how to combine them. But that doesn't mean we can't write our own valueof!
Creating your own `ValueOf`
\n\nThe simplest way is to use an indexed access type in combination with keyof:
type ValueOf<T> = T[keyof T];\n\ntype PersonValues = ValueOf<Person>; // string | number | boolean\n\nThat's it! We just created a generic type ValueOf that works like valueof. But let's dig deeper — how does this affect performance and how to use it wisely.
Optimization: when `ValueOf` saves you from duplication
\n\nImagine you have a configuration object with dozens of fields. You want to write a function that accepts any value from this object. Without ValueOf, you would list the types manually:
type Config = {\n apiUrl: string;\n timeout: number;\n retries: number;\n debug: boolean;\n};\n\n// Bad: type duplication\nfunction setConfigValue(key: string, value: string | number | boolean) {\n // ...\n}\n\nAnd now with ValueOf:
// Good: automatically picks up all value types\nfunction setConfigValue(key: keyof Config, value: ValueOf<Config>) {\n // TypeScript knows that value can only be string | number | boolean\n}\n\nThis not only reduces code but also makes it self-documenting. If you add a new field to Config, TypeScript will automatically pick up the new type. Fewer errors — more development performance.
Advanced `ValueOf` with conditional types
\n\nSometimes you need to get values only from certain keys. For example, all numeric values. This is where conditional types come to the rescue:
\n\ntype NumericValues<T> = {\n [K in keyof T]: T[K] extends number ? T[K] : never;\n}[keyof T];\n\ntype ConfigNumeric = NumericValues<Config>; // number (timeout | retries)\n\nThis technique is especially useful when working with large types: you can filter only the needed values and avoid unnecessary runtime checks. Optimization at the type level is free performance, because types disappear during compilation.
\n\nRuntime performance: is it necessary?
\n\nAn important point: ValueOf is a purely type-level construct. It does not generate any JavaScript code. But its correct use can indirectly improve the performance of your application:
- \n
- Fewer bugs — less time spent debugging. \n
- Stricter typing — the compiler catches