@tmlmobilidade/types 20250828.1338.25 → 20250828.1439.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,3 +5,4 @@ export * from './fastify.js';
5
5
  export * from './operational-date.js';
6
6
  export * from './proposed-change.js';
7
7
  export * from './unix-timestamp.js';
8
+ export * from './utility.js';
@@ -5,3 +5,4 @@ export * from './fastify.js';
5
5
  export * from './operational-date.js';
6
6
  export * from './proposed-change.js';
7
7
  export * from './unix-timestamp.js';
8
+ export * from './utility.js';
@@ -0,0 +1,83 @@
1
+ /**
2
+ * A type that represents either a single instance of type T or an array of type T.
3
+ *
4
+ * @template T - The type of the element(s).
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * function processItems<T>(items: OneOrMore<T>) {
9
+ * const arr = Array.isArray(items) ? items : [items];
10
+ * console.log(arr);
11
+ * }
12
+ *
13
+ * processItems("apple"); // ["apple"]
14
+ * processItems(["a", "b"]); // ["a", "b"]
15
+ * ```
16
+ */
17
+ export type OneOrMore<T> = T | T[];
18
+ /**
19
+ * A type that represents either A or B, but not both.
20
+ *
21
+ * @template A - The first type.
22
+ * @template B - The second type.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * type Credentials = OneOrTheOther<{ email: string }, { username: string }>;
27
+ *
28
+ * const a: Credentials = { email: "a@b.com" }; // ✅
29
+ * const b: Credentials = { username: "user1" }; // ✅
30
+ * const c: Credentials = { email: "a@b.com", username: "user1" }; // ❌
31
+ * ```
32
+ */
33
+ export type OneOrTheOther<A, B> = (A & {
34
+ [K in keyof B]?: never;
35
+ }) | (B & {
36
+ [K in keyof A]?: never;
37
+ });
38
+ /**
39
+ * A type that represents exactly one key-value pair in the object T.
40
+ *
41
+ * @template T - The type of the object.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ type Action = ExactlyOne<{
46
+ create: { name: string };
47
+ update: { id: string; name?: string };
48
+ delete: { id: string };
49
+ }>;
50
+
51
+ const x: Action = { create: { name: "New" } }; // ✅
52
+ const y: Action = { update: { id: "123" } }; // ✅
53
+ const z: Action = { create: { name: "X" }, delete: { id: "1" } }; // ❌
54
+ * ```
55
+ */
56
+ export type ExactlyOne<T> = {
57
+ [K in keyof T]: Partial<Record<Exclude<keyof T, K>, never>> & {
58
+ [P in K]: T[P];
59
+ };
60
+ }[keyof T];
61
+ /**
62
+ * A type that represents either none or exactly one key-value pair in the object T.
63
+ *
64
+ * @template T - The type of the object.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * type Filters = { name: string; age: number; email: string };
69
+ * type FilterChoice = NoneOrExactlyOne<Filters>;
70
+ *
71
+ * const a: FilterChoice = {}; // ✅ none
72
+ * const b: FilterChoice = { name: "Alice" }; // ✅ exactly one
73
+ * const c: FilterChoice = { age: 30 }; // ✅ exactly one
74
+ * const d: FilterChoice = { name: "Alice", age: 30 }; // ❌ error
75
+ * ```
76
+ */
77
+ export type NoneOrExactlyOne<T> = {
78
+ [K in keyof T]: Partial<Record<Exclude<keyof T, K>, never>> & {
79
+ [P in K]: T[P];
80
+ };
81
+ }[keyof T] | {
82
+ [K in keyof T]?: never;
83
+ };
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/types",
3
- "version": "20250828.1338.25",
3
+ "version": "20250828.1439.42",
4
4
  "author": "João de Vasconcelos & Jusi Monteiro",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "homepage": "https://github.com/tmlmobilidade/services#readme",