1. Introduction
keyof and typeof are two of TypeScript's core type-level query operators. keyof T inspects an existing type and produces a union of string (and sometimes number or symbol) literal types representing its property names. typeof x, when used in a type position (as opposed to a JavaScript expression position), extracts the static type TypeScript has inferred for a value — this is different from JavaScript's runtime typeof operator, which returns a string like "string" or "object" at runtime. Combined, they let you derive types from values and reflect over a type's shape without duplicating definitions.
Cricket analogy: Think of keyof as reading Virat Kohli's scorecard and listing only the column headers (runs, balls, fours, sixes) as a set of valid labels, while typeof is like inferring a batsman's role from his stats sheet rather than declaring it beforehand.
2. Syntax
interface Point {
x: number;
y: number;
}
type PointKeys = keyof Point; // "x" | "y"
const origin = { x: 0, y: 0, label: "origin" };
type OriginType = typeof origin; // { x: number; y: number; label: string }
type OriginKeys = keyof typeof origin; // "x" | "y" | "label"
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}3. Explanation
keyof T produces a union of a type's property names as string literal types (plus number/symbol literals for index signatures or numerically-named members). It is most commonly combined with a generic constraint, <K extends keyof T>, to write type-safe property accessors like getProp above, where the return type T[K] (an indexed access type) is precisely the type of the requested property rather than a broad any.
Cricket analogy: Restricting K to keyof Scorecard is like telling a scorer they may only query fields that exist on the sheet (runs, wickets), so getProp("runs") returns exactly a number, never a vague any.
typeof in a type annotation position reads the compiler's already-inferred static type of a variable, function, or other value declaration, and reifies it as a usable type. This is the reverse direction of normal typing: instead of writing a type and then a value that satisfies it, you write the value first (often a const object, enum-like object, or config) and derive the type from it with typeof, keeping a single source of truth. Combining both, keyof typeof someObject is an extremely common pattern for deriving a union of literal keys directly from a runtime object without maintaining a separate type declaration.
Cricket analogy: Declaring a const lineup object first and deriving its type with typeof is like naming your playing XI on paper, then letting the scoreboard software infer the roster type from that list instead of typing it twice; keyof typeof lineup then gives you every player's name as a valid key.
keyof any is string | number | symbol — the universal set of valid property key types in JavaScript — and is commonly used as a generic constraint for anything that can be used as an object key.
Gotcha: type-position typeof is not the same operator as JavaScript's runtime typeof. typeof x in an expression (e.g. inside an if) evaluates at runtime to a string like "number"; typeof x in a type annotation (e.g. let y: typeof x) is resolved entirely at compile time and erased — it never executes. TypeScript disambiguates them by parsing position, but conflating the two is a frequent source of confusion for developers new to advanced TypeScript.
4. Example
const config = {
host: "localhost",
port: 8080,
debug: true,
};
type Config = typeof config;
type ConfigKey = keyof Config; // "host" | "port" | "debug"
function getConfigValue<K extends ConfigKey>(key: K): Config[K] {
return config[key];
}
console.log(getConfigValue("host"));
console.log(getConfigValue("port"));
console.log(getConfigValue("debug"));
const keys: ConfigKey[] = Object.keys(config) as ConfigKey[];
console.log(keys.join(", "));5. Output
localhost
8080
true
host, port, debug6. Key Takeaways
keyof Tproduces a union of a type's property name literals.typeof xin a type position extracts the static type of a value, unlike JS runtimetypeof.keyof typeof objis a common pattern for deriving key unions fromconstobjects.keyof anyequalsstring | number | symbol, the universal object-key type.- Combining
<K extends keyof T>withT[K]yields precise, type-safe property accessors.
Practice what you learned
1. What does `keyof Point` produce for `interface Point { x: number; y: number }`?
2. Gotcha: what is the key difference between `typeof x` used inside an `if (typeof x === "string")` versus `let y: typeof x`?
3. What does `keyof any` evaluate to?
4. In `function getProp<T, K extends keyof T>(obj: T, key: K): T[K]`, what does `T[K]` represent?
5. What is the most idiomatic way to derive a literal union of keys directly from a `const` object without writing a separate interface?
Was this page helpful?
You May Also Like
Mapped Types in TypeScript
Transform every property of an existing type into a new type using `{ [K in keyof T]: ... }`, with modifiers and key remapping.
Conditional Types in TypeScript
Branch at the type level with `T extends U ? X : Y`, including how distributive conditional types behave over union types.
Type Guards in TypeScript
Narrow union types safely within conditional blocks using `typeof`, `instanceof`, and custom user-defined type predicates with `is`.
Utility Types in TypeScript
Learn TypeScript's built-in generic utility types — Partial, Required, Readonly, Pick, Omit, and Record — for transforming existing types.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics