> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript Mapped Type

A mapped type is a type expression that constructs a new object type by iterating over a union of property keys. It operates as a type-level comprehension, applying a specific transformation to each key and its associated value type to produce a derived object signature. Structurally, mapped types can only be declared using type aliases (`type`); attempting to define a mapped type within an `interface` declaration violates TypeScript syntax rules and will throw an error.

## Base Syntax

The foundation of a mapped type relies on the `in` operator to iterate over a union of keys. These keys can be literal types, a union derived from an existing type, or the broad primitive types `string`, `number`, and `symbol`.

```typescript theme={"dark"}
// Iterating over a literal union
type Flags = {
  [K in "a" | "b"]: boolean;
};

// Iterating over the keys of a generic type T
type Mapped<T> = {
  [K in keyof T]: T[K];
};

// Invalid: Cannot be declared via interface
// interface Flags { [K in "a" | "b"]: boolean; } // Syntax Error
```

* **`K`**: A type variable representing the current key in the iteration.
* **`in`**: The iteration operator that loops over the specified union of keys.
* **`keyof T`**: The index type query operator that yields the union of known, public property names of `T`.
* **`T[K]`**: The indexed access type, resolving to the type of the property `K` in the original type `T`.

## Homomorphic Mapped Types and Modifier Preservation

When a mapped type iterates directly over the keys of an existing type using the `keyof` operator (e.g., `[K in keyof T]`), it is classified as a *homomorphic* mapped type. A critical characteristic of homomorphic mapped types is **modifier preservation**. By default, TypeScript automatically inherits and preserves the original `readonly` and optional (`?`) modifiers of the source type `T` in the resulting mapped type.

```typescript theme={"dark"}
type Source = {
  readonly a: string;
  b?: number;
};

type Preserved<T> = {
  [K in keyof T]: T[K] | null;
};

// Preserved<Source> resolves to:
// { readonly a: string | null; b?: number | null; }
```

## Mapping Modifiers

To override the default preservation behavior, mapped types can explicitly mutate the mutability (`readonly`) and optionality (`?`) of properties during the iteration process. These modifiers accept addition (`+`) or subtraction (`-`) prefixes to explicitly add or remove the mapping trait. If no prefix is provided, `+` is implicitly applied.

```typescript theme={"dark"}
type MutableAndRequired<T> = {
  -readonly [K in keyof T]-?: T[K];
};

type ReadonlyAndOptional<T> = {
  +readonly [K in keyof T]+?: T[K];
};
```

## Arrays and Tuples

Homomorphic mapped types exhibit specialized behavior when applied to array and tuple types. Instead of iterating over the array prototype properties (such as `push`, `pop`, or `length`), TypeScript maps strictly over the individual elements. This produces a new array or tuple type of the exact same length, applying the mapped transformation to the element types rather than returning a standard object type containing array methods as keys.

```typescript theme={"dark"}
type Stringify<T> = {
  [K in keyof T]: string;
};

type Tuple = [number, boolean];
type StringifiedTuple = Stringify<Tuple>; 
// Resolves to: [string, string]
// Does NOT resolve to: { push: string; length: string; 0: string; 1: string; }
```

## Key Remapping via `as`

TypeScript allows the transformation of the keys themselves during iteration using the `as` clause. This evaluates a template literal type or another type transformation to generate a new property key.

```typescript theme={"dark"}
type RemappedKeys<T> = {
  [K in keyof T as `new_${string & K}`]: T[K];
};
```

### Key Filtering

The `as` clause can also filter out properties during the mapping phase. If the `as` clause evaluates to the `never` type, that property is omitted entirely from the resulting mapped type.

```typescript theme={"dark"}
type FilteredType<T, U> = {
  [K in keyof T as K extends U ? never : K]: T[K];
};
```

## Iterating Over Broad Primitives

When a mapped type iterates over the broad primitive types `string`, `number`, or `symbol` rather than specific literal types, the resulting type expression generates an index signature instead of discrete properties.

```typescript theme={"dark"}
type StringMap = {
  [K in string]: boolean; 
};
// Resolves to an index signature: { [x: string]: boolean; }
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor TypeScript Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
