Skip to content

Commit 61089ad

Browse files
committed
Improve objectToEntries type safety and docs
Updated objectToEntries to return ReadonlyArray for better immutability guarantees and improved the documentation with a clearer example and explanation of branded key preservation.
1 parent 37b9f69 commit 61089ad

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

packages/common/src/Evolu/Query.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Brand } from "../Brand.js";
12
import { bytesToHex, hexToBytes } from "../Buffer.js";
23
import { objectToEntries } from "../Object.js";
34
import {
@@ -9,7 +10,6 @@ import {
910
} from "../Sqlite.js";
1011
import { Store, StoreSubscribe } from "../Store.js";
1112
import { Simplify } from "../Types.js";
12-
import { Brand } from "../Brand.js";
1313

1414
/**
1515
* A type-safe SQL query.
@@ -52,7 +52,7 @@ export const serializeQuery = <R extends Row>(query: SqliteQuery): Query<R> => {
5252
);
5353

5454
const options = query.options
55-
? objectToEntries(query.options).sort(([a], [b]) => a.localeCompare(b))
55+
? objectToEntries(query.options).toSorted(([a], [b]) => a.localeCompare(b))
5656
: [];
5757

5858
return JSON.stringify([query.sql, params, options]) as Query<R>;

packages/common/src/Object.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,22 @@ export type ReadonlyRecord<K extends keyof any, V> = Readonly<Record<K, V>>;
2525
type StringKeyOf<T> = Extract<keyof T, string>;
2626

2727
/**
28-
* Converts a record to entries, preserving branded string key types (e.g.,
29-
* `type Id = 'id' & string`) via `StringKeyOf<T>`, unlike `Object.entries`
30-
* which widens keys to `string`.
28+
* Like `Object.entries` but preserves branded keys.
29+
*
30+
* ### Example
31+
*
32+
* ```ts
33+
* type UserId = string & { readonly __brand: "UserId" };
34+
* const users: Record<UserId, string> = {};
35+
* const entries = objectToEntries(users); // [UserId, string][]
36+
* ```
3137
*/
3238
export const objectToEntries = <T extends Record<string, any>>(
3339
record: T,
34-
): Array<[StringKeyOf<T>, T[StringKeyOf<T>]]> =>
35-
Object.entries(record) as Array<[StringKeyOf<T>, T[StringKeyOf<T>]]>;
40+
): ReadonlyArray<[StringKeyOf<T>, T[StringKeyOf<T>]]> =>
41+
Object.entries(record) as Array<
42+
[StringKeyOf<T>, T[StringKeyOf<T>]]
43+
> as ReadonlyArray<[StringKeyOf<T>, T[StringKeyOf<T>]]>;
3644

3745
/**
3846
* Maps a `ReadonlyRecord<K, V>` to a new `ReadonlyRecord<K, U>`, preserving

0 commit comments

Comments
 (0)