# @helpers4/type

> Tree-shakable TypeScript utility functions for the `type` domain.
> Package: `@helpers4/type` — Version: 3.0.1
> License: LGPL-3.0-or-later

## Installation

```sh
npm install @helpers4/type
# or
pnpm add @helpers4/type
```

## Usage

```typescript
import { Brand, DeepGet, DeepPartial, ... } from '@helpers4/type';
```

## Functions

| Function | Description |
|---|---|
| `Brand` | Brands a base type `T` with a phantom tag `B` to create a nominal type.  Two `Brand<string, 'UserId' |
| `DeepGet` | Resolves the value type at a given `Path` within `T`.  Returns `unknown` when any key in `Path` is n |
| `DeepPartial` | Recursively makes all properties of T optional, including nested objects and array elements. |
| `DeepSet` | Produces the type of `T` after replacing the value at `Path` with `V`.  When a key in `Path` is abse |
| `DeepWritable` | Recursively removes `readonly` from all properties of T, including nested objects, array elements, a |
| `KeysOfType` | Extracts the keys of `T` whose values extend `V`.  Optional properties are matched by their non-null |
| `Maybe` | Type for values that can be T, undefined, or null. |
| `Nullable` | Adds `null` to a type (`T | null`).  Useful as a shorthand when explicit nullability should be expre |
| `Nullish` | Adds `null` and `undefined` to a type (`T | null | undefined`).  Alias of Maybe. |
| `OmitByValue` | Constructs a type by omitting all entries of `T` whose values extend `V`.  Optional properties are m |
| `OptionalKeys` | Extracts the optional keys of an object type `T`. |
| `PickByValue` | Constructs a type by picking all entries of `T` whose values extend `V`.  Optional properties are ma |
| `Prettify` | Flattens an intersection type into a single readable object type.  IDE tooltips for intersections li |
| `RequiredKeys` | Extracts the required (non-optional) keys of an object type `T`. |
| `UnionToIntersection` | Converts a union type to an intersection type: `A | B | C` → `A & B & C`.  Uses conditional-type dis |
| `ValueOf` | Produces a union of all value types of an object type `T`. |

---

## API Reference

### `Brand`

Brands a base type `T` with a phantom tag `B` to create a nominal type.

Two `Brand<string, 'UserId'>` and `Brand<string, 'Email'>` are structurally
identical strings at runtime, but TypeScript treats them as distinct types
at the call site — preventing accidental mix-ups.

Use a const-assertion cast at the creation boundary:
```ts
type UserId = Brand<string, 'UserId'>;
const toUserId = (s: string): UserId => s as UserId;
```

**Examples:**

*Brand*

```typescript
```ts
type Meter = Brand<number, 'Meter'>;
type Second = Brand<number, 'Second'>;

declare function speed(distance: Meter, time: Second): number;
const d = 100 as Meter;
const t = 5 as Second;
speed(d, t);   // ✅
speed(t, d);   // ✗ Type error — args swapped
```
```

---

### `DeepGet`

Resolves the value type at a given `Path` within `T`.

Returns `unknown` when any key in `Path` is not present in the corresponding
level of `T`. An empty path resolves to `T` itself. A path segment that goes
through an optional property keeps the result nullable (`V | undefined`)
instead of degrading to `unknown`.

**Examples:**

*DeepGet*

```typescript
```ts
type Obj = { a: { b: { c: number } } };

DeepGet<Obj, ['a', 'b', 'c']> // => number
DeepGet<Obj, ['a', 'b']>      // => { c: number }
DeepGet<Obj, ['a', 'x']>      // => unknown
DeepGet<Obj, []>              // => Obj

type WithOptional = { a?: { b: number } };
DeepGet<WithOptional, ['a', 'b']> // => number | undefined
```
```

---

### `DeepPartial`

Recursively makes all properties of T optional, including nested objects
and array elements.

**Examples:**

*DeepPartial*

```typescript
```ts
type Config = { server: { host: string; port: number }; debug: boolean };
type PartialConfig = DeepPartial<Config>;
// => { server?: { host?: string; port?: number }; debug?: boolean }
```
```

---

### `DeepSet`

Produces the type of `T` after replacing the value at `Path` with `V`.

When a key in `Path` is absent from the corresponding level of `T`, that level
(and everything below it) is added as a new field instead of resolving to
`never` — mirroring how `set()` creates intermediate objects at runtime.

**Examples:**

*DeepSet*

```typescript
```ts
type Obj = { a: { b: number; c: string } };

DeepSet<Obj, ['a', 'b'], string>
// => { a: { b: string; c: string } }

DeepSet<Obj, ['a', 'x'], boolean>
// => { a: { b: number; c: string } & { x: boolean } }
```
```

---

### `DeepWritable`

Recursively removes `readonly` from all properties of T, including nested
objects, array elements, and tuple positions.

**Examples:**

*DeepWritable*

```typescript
```ts
type Config = { readonly server: { readonly host: string }; readonly tags: readonly string[] };
type MutableConfig = DeepWritable<Config>;
// => { server: { host: string }; tags: string[] }
```
```

*DeepWritable*

```typescript
```ts
type Point = readonly [x: number, y: number];
type MutablePoint = DeepWritable<Point>;
// => [x: number, y: number]

Note: `Date`, `Map`, `Set`, `Promise`, and `RegExp` are treated as opaque and passed
through unchanged. In particular, `DeepWritable<Map<K, V>>` does **not** strip `readonly`
from the value type `V` — use a manual mapped type if you need that.
```
```

---

### `KeysOfType`

Extracts the keys of `T` whose values extend `V`.

Optional properties are matched by their non-nullable value type, so an
optional `string` property still counts as a `string` key.

**Examples:**

*KeysOfType*

```typescript
```ts
type User = { id: number; name: string; email: string; active: boolean };
type StringKeys = KeysOfType<User, string>; // 'name' | 'email'
type NumberKeys = KeysOfType<User, number>; // 'id'
```
```

---

### `Maybe`

Type for values that can be T, undefined, or null.

---

### `Nullable`

Adds `null` to a type (`T | null`).

Useful as a shorthand when explicit nullability should be expressed
in function signatures or generic constraints.

**Examples:**

*Nullable*

```typescript
```ts
type MaybeUser = Nullable<User>; // User | null

function findUser(id: string): Nullable<User> { ... }
```
```

---

### `Nullish`

Adds `null` and `undefined` to a type (`T | null | undefined`).

Alias of Maybe.

**Examples:**

*Nullish*

```typescript
```ts
type OptionalUser = Nullish<User>; // User | null | undefined
```
```

---

### `OmitByValue`

Constructs a type by omitting all entries of `T` whose values extend `V`.

Optional properties are matched by their non-nullable value type, so an
optional `string` property is omitted the same as a required one.

**Examples:**

*OmitByValue*

```typescript
```ts
type Form = { name: string; age: number; email: string; active: boolean };
type NonStringFields = OmitByValue<Form, string>; // { age: number; active: boolean }
```
```

---

### `OptionalKeys`

Extracts the optional keys of an object type `T`.

**Examples:**

*OptionalKeys*

```typescript
```ts
type User = { id: number; name: string; email?: string };
type Opts = OptionalKeys<User>; // 'email'
```
```

---

### `PickByValue`

Constructs a type by picking all entries of `T` whose values extend `V`.

Optional properties are matched by their non-nullable value type, so an
optional `string` property is picked the same as a required one.

**Examples:**

*PickByValue*

```typescript
```ts
type Form = { name: string; age: number; email: string; active: boolean };
type StringFields = PickByValue<Form, string>; // { name: string; email: string }
```
```

---

### `Prettify`

Flattens an intersection type into a single readable object type.

IDE tooltips for intersections like `A & B & C` often show the raw
intersection instead of the resolved shape. Wrapping with `Prettify`
forces TypeScript to expand and display the fully-resolved type.

Distributes over unions, so each member is prettified independently
instead of collapsing to their shared keys.

**Examples:**

*Prettify*

```typescript
```ts
type A = { a: number };
type B = { b: string };
type Merged = A & B;        // shown as "A & B" in IDE
type Pretty = Prettify<Merged>; // shown as "{ a: number; b: string }"
```
```

---

### `RequiredKeys`

Extracts the required (non-optional) keys of an object type `T`.

**Examples:**

*RequiredKeys*

```typescript
```ts
type User = { id: number; name: string; email?: string };
type Required = RequiredKeys<User>; // 'id' | 'name'
```
```

---

### `UnionToIntersection`

Converts a union type to an intersection type: `A | B | C` → `A & B & C`.

Uses conditional-type distribution and the contravariant position of a
function parameter to collapse the union into an intersection.

**Examples:**

*UnionToIntersection*

```typescript
```ts
type Union = { a: number } | { b: string } | { c: boolean };
type Intersection = UnionToIntersection<Union>;
// { a: number } & { b: string } & { c: boolean }

type Keys = UnionToIntersection<'a' | 'b'>;
// 'a' & 'b'  (resolves to never for disjoint literals)
```
```

---

### `ValueOf`

Produces a union of all value types of an object type `T`.

**Examples:**

*ValueOf*

```typescript
```ts
type Config = { host: string; port: number; secure: boolean };
type ConfigValue = ValueOf<Config>; // string | number | boolean

const STATUS = { OK: 200, NOT_FOUND: 404, ERROR: 500 } as const;
type StatusCode = ValueOf<typeof STATUS>; // 200 | 404 | 500
```
```

---
