Skip to main content

Using TypeScript typeof for advance type safety

The typeof operator in TypeScript is a valuable tool for capturing the type of a variable at compile time. It's essential for type checking and inference in complex applications, helping make your code more maintainable, type-safe, and easy to understand.

Using typeof for Type Checking

In TypeScript, typeof captures a variable's type structure during compile time, which is especially useful for type checking and safety. Here's how you can use it:

const name: string = 'John';
console.log(typeof name === 'string'); // true
type NameType = typeof name;

In this case, NameType will be recognized as string.

Inferring Variable Types with typeof

You can apply typeof to variables to infer their types, aiding in maintaining type consistency. Consider this example using a type inference pattern:

// Server configuration object
const serverConfig = {
port: 8080,
host: 'localhost',
database: {
url: 'mongodb://localhost:27017',
name: 'myapp'
},
maxConnections: 1000
};

// Infer the type automatically
type ServerConfig = typeof serverConfig;

// Now TypeScript knows the exact shape
function startServer(config: ServerConfig) {
// TypeScript provides full autocomplete and type checking
const { port, host, database } = config;
}

Differences Between typeof in TypeScript and JavaScript

Both JavaScript and TypeScript use typeof to determine a variable's type, but TypeScript extends its functionality by allowing typeof in type contexts, making it a compile-time feature. The main differences are:

FeatureJavaScript typeofTypeScript typeof
PurposeRuntime type checkCompile-time type reference
ReturnString ("number", "object", etc.)Type structure

For example, in JavaScript, typeof returns a string at runtime:

function handleValue(value: any) {
if (typeof value === 'string') {
return value.toUpperCase();
}
return String(value);
}

In TypeScript, typeof creates a static type from an existing value:

const user = {
id: 1,
name: 'Alex',
roles: ['admin', 'editor']
};

type User = typeof user;
// Results in type:
// {
// id: number;
// name: string;
// roles: string[];
// }

Ensuring Type Safety for Constants with typeof

Constants often define important application settings. Here's how to use typeof with different types of constants:

// Simple constants
const MAX_RETRIES = 3;
const API_VERSION = 'v2';
type MaxRetries = typeof MAX_RETRIES; // type: 3
type ApiVersion = typeof API_VERSION; // type: "v2"

// Constant objects
const API_ENDPOINTS = {
users: '/api/users',
posts: '/api/posts',
comments: '/api/comments'
} as const; // Make all properties readonly

type ApiEndpoints = typeof API_ENDPOINTS;
// Results in:
// {
// readonly users: "/api/users";
// readonly posts: "/api/posts";
// readonly comments: "/api/comments";
// }

Notice how const makes the types more specific - instead of just string, we get the exact string literals. This helps catch typos and invalid valuesat compile time.

Inferring Function Return Types with typeof

Using typeof with functions is particularly useful when working withTypeScript in a database or API context. Consider this example:

// Function with complex return type
function fetchUserData(id: string) {
return {
id,
name: 'Sarah Smith',
preferences: {
theme: 'dark',
notifications: true
},
lastLogin: new Date()
};
}

// Get the return type
type UserData = ReturnType<typeof fetchUserData>;

// Get the function type itself
type FetchUserFn = typeof fetchUserData;

// Now you can use these types
const cachedFetch: FetchUserFn = (id: string) => {
// Implementation with type checking
};

const userData: UserData = {
id: '123',
name: 'John Doe',
preferences: {
theme: 'light',
notifications: false
},
lastLogin: new Date()
};

Combining typeof with Other TypeScript Utility Types

Type narrowing becomes more powerful when you combine typeof with utility types like Partial or Readonly to boost type safety. For example:

// Start with a configuration object
const defaultSettings = {
theme: 'light',
fontSize: 16,
notifications: {
email: true,
push: false,
frequency: 'daily'
}
};

// Make all fields optional
type PartialSettings = Partial<typeof defaultSettings>;

// Make all fields readonly
type ReadonlySettings = Readonly<typeof defaultSettings>;

// Pick specific fields
type ThemeSettings = Pick<typeof defaultSettings, 'theme' | 'fontSize'>;

// Create a type for updates
function updateSettings(updates: PartialSettings) {
// Type-safe partial updates
}

// Use in practice
updateSettings({ fontSize: 20 }); // Valid
updateSettings({ notifications: { email: false } }); // Valid
updateSettings({ invalid: true }); // Error: invalid property

Common Errors with typeof

Errors can occur if typeof is misused, such as when applied to imported modules or complex expressions. To avoid issues, understand its scope and limitations.

// Mistake 1: Using typeof with type imports
import { UserType } from './types';
type NewType = typeof UserType; // Error: 'UserType' refers to a type, but is used as a value

// Fix: Use the type directly
import type { UserType } from './types';
type NewType = UserType;

// Mistake 2: typeof with generic functions
function getValue<T>(value: T) {
return value;
}
type ValueType = typeof getValue; // Gets function type, not the generic return type

// Fix: Use ReturnType and specify the generic
type StringValue = ReturnType<typeof getValue<string>>;

// Mistake 3: Using typeof on non-values
type Status = 'active' | 'inactive';
type StatusType = typeof Status; // Error: 'Status' refers to a type, but is used as a value

// Fix: Define a const value if you need typeof
const statusValues = ['active', 'inactive'] as const;
type Status = typeof statusValues[number];

Final Thoughts on TypeScript typeof

The typeof operator helps you write type-safe code by:

  • Extracting types from existing values and variables

  • Working seamlessly with utility types for flexible type manipulation

  • Providing compile-time safety while maintaining JavaScript's runtime type checking

For more advanced TypeScript patterns, check out our posts on TypeScript and API generation.