# TypeScript `const` Assertions (`as const`)

TypeScript 3.4 introduced a new construct for literal values called `const` assertions. Its syntax is a type assertion with `const` in place of the type name (e.g., `123 as const`).

When you construct a new literal expression with a `const` assertion, you signal to the compiler:
1.  **No Widening:** Literal types should not be widened (e.g., no going from `"hello"` to `string`).
2.  **Readonly:** Object properties get `readonly` modifiers.
3.  **Tuples:** Arrays become `readonly` tuples.

## 1. Preventing Type Widening

By default, if you assign a string literal to a variable (using `let`), TypeScript infers it as `string`.

```typescript
// Type: string
let x = "hello";

// Type: "hello"
let y = "hello" as const;
```

This is useful when you want to ensure a variable holds a specific literal value and nothing else.

## 2. Objects become Readonly

When you use `as const` on an object, all its properties automatically become `readonly`, and their types are narrowed to their literal values.

```typescript
const config = {
  endpoint: "https://api.example.com",
  retries: 3
};
// Type: { endpoint: string; retries: number; }
// Properties are mutable.

const strictConfig = {
  endpoint: "https://api.example.com",
  retries: 3
} as const;
// Type: { readonly endpoint: "https://api.example.com"; readonly retries: 3; }
// Properties are immutable.

// strictConfig.retries = 5; // Error: Cannot assign to 'retries' because it is a read-only property.
```

## 3. Arrays become Readonly Tuples

By default, an array of mixed types is inferred as `(TypeA | TypeB)[]`. With `as const`, it becomes a fixed-length, readonly tuple.

```typescript
const args = [8, 5];
// Type: number[]

const strictArgs = [8, 5] as const;
// Type: readonly [8, 5]
```

This is extremely useful for React hooks or functions that return tuples.

```typescript
function useToggle() {
  let state = true;
  const toggle = () => state = !state;
  
  // Without 'as const', TS infers (boolean | () => boolean)[]
  // With 'as const', TS infers readonly [boolean, () => boolean]
  return [state, toggle] as const;
}

const [value, set] = useToggle();
// value is boolean
// set is () => boolean
```

## 4. Complex Nested Structures

`as const` applies recursively.

```typescript
const menu = {
  home: { label: "Home", link: "/" },
  about: { label: "About", link: "/about" }
} as const;
```

[[programming/javascript/typescript/typescript]]