Skip to content

Commit

Permalink
feat(object/types): init
Browse files Browse the repository at this point in the history
- `Key` is a valid object key.

- `Entry` is a key-value tuple.

- `Pair` is a key-value pair in an object.

- `EntryToPair` converts an `Entry` to a `Pair`

- `FromEntries` converts `Entry`s to an object

- `ToEntries` converts an object to an array of `Entry`s

- The `Obj` namespace clusters these helper types.
  • Loading branch information
pskfyi committed May 26, 2023
1 parent e3b017f commit 0d9846c
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
1 change: 1 addition & 0 deletions object/mod.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./types.ts";
export * from "./utils.ts";
59 changes: 59 additions & 0 deletions object/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Pretty } from "../ts/types.ts";

/** A valid object key. */
export type Key = string | number | symbol;

/** A key-value tuple. Similar to the outputs of `Object.entries` and
* the inputs to `Object.fromEntries`, except numbers are not stringified
* and symbols are allowed. This is primarily used for `extends` clauses
* to ensure that an input conforms to this shape.
*
* @example
* type MyEntry = Obj.Entry<unknown>; // [Obj.Key, unknown] */
export type Entry<V = unknown> = [key: Key, value: V];

/** An object intended to house a single key-value pair. The object-shaped
* equivalent of `Obj.Entry`. Mostly the same as TS's builtin `Record` type
* but provided here for parity with other object types.
*
* @example
* type MyPair = Obj.Pair<"a", 1>;
* // { a: 1 } */
export type Pair<K extends Key, V> = Pretty<{ [_ in K]: V }>;

/** Converts an `Obj.Entry` to an `Obj.Pair`.
*
* @example
* type MyPair = Obj.EntryToPair<["a", 1]>;
* // { a: 1 } */
export type EntryToPair<T extends Entry> = T extends
[infer K extends Key, infer Value] ? Pair<K, Value>
: never;

type _EntriesToObject<T extends Entry[]> = T extends [] ? Record<never, never>
: T extends [infer Head extends Entry, ...infer Tail extends Entry[]]
? EntryToPair<Head> & _EntriesToObject<Tail>
: never;

/** Converts an array of `Obj.Entry`s to an object. Analogous to
* `Object.fromEntries`.
*
* @example
* type MyObj = Obj.FromEntries<[["a", 1], ["b", 2]]>;
* // { a: 1, b: 2 } */
export type FromEntries<T extends Entry[]> = Pretty<_EntriesToObject<T>>;

/** Convert an object to an array of `Obj.Entry`s. Unfortunately, this
* cannot return a tuple which would preserve the order of the keys, due to
* current limitations in TypeScript.
*
* @example
* type MyEntries = Obj.ToEntries<{ a: 1, b: 2 }>;
* // Array<["a", 1], ["b", 2]> */
export type ToEntries<T> = {
[K in keyof T]: [K, T[K]];
}[keyof T][];

export declare namespace Obj {
export { Entry, EntryToPair, FromEntries, Key, Pair, ToEntries };
}
11 changes: 11 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,17 @@ const S = Symbol("symbol");
setNestedEntry({}, ["a", 10, S], "👋"); // { a: { 10: { [S]: "👋" } } }
```

```ts
import type { Obj } from "https://deno.land/x/handy/object/types.ts";

type Key = Obj.Key; // string | number | symbol
type Entry = Obj.Entry<any>; // [Key, any]
type Pair = Obj.Pair<"a", number>; // { "a": number }
type EntryToPair = Obj.EntryToPair<Entry>; // Pair
type MyObj = Obj.FromEntries<[["a", 1], ["b", null]]>; // { a: 1, b: null }
type Entries = Obj.ToEntries<MyObj>; // Array<["a", 1], ["b", null]>
```

## `os`

OS-related utilities.
Expand Down

0 comments on commit 0d9846c

Please sign in to comment.