TypeScript as const: Stop Type Widening for Good
Problem
You define a constants object, but TypeScript widens the types:
const STATUS = {
PENDING: 'pending',
ACTIVE: 'active',
CLOSED: 'closed',
};
// Type: { PENDING: string, ACTIVE: string, CLOSED: string }
// Just 'string', not the literal types you wanted
STATUS.PENDING is typed as string, so it won’t match a parameter expecting 'pending' | 'active' | 'closed'.
Solution
Add as const:
const STATUS = {
PENDING: 'pending',
ACTIVE: 'active',
CLOSED: 'closed',
} as const;
// Type: { readonly PENDING: 'pending', readonly ACTIVE: 'active', readonly CLOSED: 'closed' }
Now STATUS.PENDING is the literal type 'pending'. You can also extract a union type:
type StatusType = typeof STATUS[keyof typeof STATUS];
// 'pending' | 'active' | 'closed'
function updateStatus(status: StatusType) {
// Only accepts one of the three values
}
updateStatus(STATUS.ACTIVE); // OK
updateStatus('random'); // Compile error
Works with arrays too:
const ROLES = ['admin', 'editor', 'viewer'] as const;
type Role = typeof ROLES[number]; // 'admin' | 'editor' | 'viewer'
// Inferred as a tuple, not string[]
// readonly ['admin', 'editor', 'viewer']
Also useful for function return values:
function getConfig() {
return {
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3,
} as const;
}
// retries is typed as 3, not number
Key Points
as constmakes all propertiesreadonlywith literal types, preventing type widening- Combine with
typeof+keyofto extract union types — no enums needed - Zero runtime overhead and better tree-shaking compared to enums