# How to Get a Variable's Type in TypeScript Using `typeof`

> Discover how to get a variable type in TypeScript using the typeof operator. Learn to capture static types for efficient code reuse and robust development.

- Repository: [Microsoft/TypeScript](https://github.com/microsoft/typescript)
- Tags: how-to-guide
- Published: 2026-02-12

---

**TypeScript's `typeof` operator functions as a compile-time type query that captures the static type of a variable, value, or class constructor, enabling type reuse without explicit manual definition.**

In the `microsoft/TypeScript` codebase, the `typeof` operator is implemented as a type query mechanism distinct from JavaScript's runtime `typeof` expression. When used in a type position, it extracts static type information during compilation rather than emitting runtime checks.

## Understanding the TypeScript `typeof` Type Query

The TypeScript `typeof` operator serves as a **type query** that evaluates exclusively at compile time. Unlike JavaScript's `typeof` which returns a string at runtime, TypeScript's version produces a type representation when placed in a type context, such as after the `type` keyword or within an interface.

The compiler resolves these queries in [`src/compiler/checker.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts), where the `getTypeOfExpression` function handles the resolution process. For identifiers, it delegates to `getTypeOfVariable`, while literal expressions route through `getTypeOfLiteral`.

## Capturing Variable and Value Types

To extract the type of a variable or value, declare a type alias using `typeof` followed by the variable name.

```typescript
const greeting = "hello";
type GreetingType = typeof greeting; // string

const config = {
  host: "localhost",
  port: 3000
};
type ConfigType = typeof config; // { host: string; port: number; }

```

The compiler infers the exact static type from the initialization value. For object literals, the checker constructs the type by analyzing property signatures stored in internal structures defined in [`src/compiler/types.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/types.ts).

## Extracting Class Constructor Types with `typeof`

When applied to a class identifier, `typeof` captures the **constructor function type** rather than the instance type. This produces a type representing the `new` signature and static members.

```typescript
class Point {
  constructor(public x: number, public y: number) {}
  static origin = new Point(0, 0);
}

type PointConstructor = typeof Point;
// new (x: number, y: number) => Point

```

This pattern is essential for factory functions and mixin patterns where you need to reference the class itself, not an instance of the class.

## Deriving Object Key Unions Using `keyof typeof`

Combining `keyof` with `typeof` creates a union type of an object's keys. This technique requires the `as const` assertion for literal type inference or operates on the existing type of a const variable.

```typescript
const colors = {
  red: "#ff0000",
  green: "#00ff00",
  blue: "#0000ff"
} as const;

type ColorName = keyof typeof colors; // "red" | "green" | "blue"
type ColorValue = typeof colors[keyof typeof colors]; // "#ff0000" | "#00ff00" | "#0000ff"

```

Under the hood, the compiler builds a `MappedType` (defined in [`src/compiler/types.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/types.ts)) to represent the object shape before extracting keys, ensuring accurate results for `keyof typeof` operations.

## Runtime Type Guards vs Compile-Time Queries

TypeScript `typeof` operates in two distinct contexts. In a **type position**, it performs compile-time type extraction. In an **expression context**, such as an `if` statement condition, it emits the standard JavaScript `typeof` operator for runtime type checking.

```typescript
function isString(value: unknown): value is string {
  return typeof value === "string";
}

function processValue(value: string | number) {
  if (typeof value === "string") {
    // TypeScript narrows type to string here
    return value.toUpperCase();
  }
  return value.toFixed(2);
}

```

The compiler's control flow analysis recognizes these runtime checks to narrow types within conditional blocks, implemented through the same type-checking infrastructure in [`src/compiler/checker.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts).

## Implementation Details in the TypeScript Compiler

The resolution of `typeof` type queries occurs primarily in [`src/compiler/checker.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts). Key functions include:

- **`getTypeOfExpression`**: Entry point for resolving `typeof` queries in type positions.
- **`getTypeOfVariable`**: Specialized handler for identifier lookups when querying variables.
- **`getTypeOfLiteral`**: Processes literal values to determine their exact types.

For complex object literals, the system utilizes `MappedType` structures (declared in [`src/compiler/types.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/types.ts)) to preserve property modifiers and optionality. Additional support utilities reside in [`src/compiler/utilities.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/utilities.ts), while public API surfaces export these capabilities through [`src/services/types.ts`](https://github.com/microsoft/TypeScript/blob/main/src/services/types.ts).

## Summary

- **TypeScript `typeof`** is a compile-time operator that extracts static types from values, distinct from JavaScript's runtime string-returning `typeof`.
- Use `typeof variable` to capture value types and `typeof ClassName` to capture constructor function types.
- Combine with `keyof` to generate unions of object keys: `keyof typeof obj`.
- The compiler implements this in [`src/compiler/checker.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts) via `getTypeOfExpression` and related functions.
- In expression contexts, `typeof` emits standard JavaScript runtime checks that enable type narrowing.

## Frequently Asked Questions

### What is the difference between TypeScript `typeof` and JavaScript `typeof`?

**TypeScript `typeof`** operates at compile time in type positions to extract type information, producing a type representation rather than a runtime value. **JavaScript `typeof`** executes at runtime and returns a string describing the value's primitive type. When used inside expressions like `if` conditions, TypeScript emits JavaScript `typeof` while also using the result for type narrowing analysis.

### Can TypeScript `typeof` extract types from class instances?

No, applying `typeof` to a class identifier captures the **constructor type** (the class itself), not the instance type. To get the instance type, use the `InstanceType` utility: `type PointInstance = InstanceType<typeof Point>`. Alternatively, `typeof` applied to an instance variable would capture that specific instance's type structure.

### How does `typeof` interact with `const` assertions?

When a variable is declared with `as const`, `typeof` extracts the most specific literal types possible rather than widening to general primitives. For example, `const x = "hello" as const` followed by `type T = typeof x` yields the literal type `"hello"` instead of `string`. This enables precise type mapping for configuration objects and dispatch tables.

### Why does my `keyof typeof` return `string` instead of literal keys?

This occurs when the object lacks a `const` assertion or when the variable is mutable and initialized with literal values. Without `as const`, TypeScript widens property types to their base primitives (e.g., `string` instead of `"red" | "green"`). Add `as const` to the object literal or declare the variable with `const` to preserve literal types for `keyof typeof` extraction.