C.W.K.
Stream
Lesson 02 of 06 · published

`typeof` (Type-Level): The Value-to-Type Bridge

~8 min · type-manipulation, typeof, type-from-value

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"You wrote a value. Now you have its type, for free."

The type-level typeof

In a type position, typeof someValue evaluates to the type of someValue. const u = { id: 1, name: 'Pippa' }; type U = typeof uU is { id: number; name: string }. The compiler reads the value's inferred type and gives you a type with that shape.

This is distinct from the runtime typeof operator (which returns a string at runtime). The type-level version exists only in type positions and is one of TypeScript's most useful features for keeping types in sync with values.

When to reach for it

Constants → types. If you have a constant and want to express the same shape as a type, typeof constant does it without retyping. const ROUTES = { CHAT: '/chat' } as const; type Routes = typeof ROUTES.

Functions → signatures. Combined with ReturnType and Parameters, you can extract a function's pieces without naming them. type Result = ReturnType<typeof fetchUser>.

External libraries. If a library exports a value but not a type for it, typeof exportedValue recovers the type.

Type-level typeof is how you make the value the source of truth and the type a derived view. The value is what runs; the type is what the compiler checks. Both come from one declaration.

Code

Value → type via typeof·typescript
// Constants to types.
const defaultUser = {
  id: 0,
  name: 'anon',
  permissions: [] as string[],
};

type User = typeof defaultUser;
// { id: number; name: string; permissions: string[] }

// Functions to signatures.
function fetchPost(id: number): Promise<{ title: string; body: string }> {
  return Promise.resolve({ title: '', body: '' });
}

type FetchPostFn = typeof fetchPost;
// (id: number) => Promise<{ title: string; body: string }>

type FetchPostReturn = ReturnType<typeof fetchPost>;
// Promise<{ title: string; body: string }>

// External library.
import { someConfig } from 'their-library';
type TheirConfig = typeof someConfig;     // recovered when they don't export the type

External links

Exercise

Take a complex config object you've written somewhere. Derive its type with typeof config and confirm the type system sees the same shape you'd write by hand. Then add as const to the config — what changes in the derived type?
Hint
Without as const, primitives widen (string field becomes string). With it, literals are preserved (string field becomes the specific literal type). The type now matches the value exactly.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.