@outfitter/types 0.1.0-rc.1

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.
@@ -0,0 +1,99 @@
1
+ /**
2
+ * General type utilities for TypeScript.
3
+ *
4
+ * @module utilities
5
+ */
6
+ /**
7
+ * Makes specific properties of a type required.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * interface Config { host?: string; port?: number; }
12
+ * type RequiredHost = RequiredKeys<Config, "host">;
13
+ * // { host: string; port?: number; }
14
+ * ```
15
+ */
16
+ type RequiredKeys<
17
+ T,
18
+ K extends keyof T
19
+ > = T & Required<Pick<T, K>>;
20
+ /**
21
+ * Makes specific properties of a type optional.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * interface User { id: string; name: string; email: string; }
26
+ * type PartialUser = OptionalKeys<User, "email">;
27
+ * // { id: string; name: string; email?: string; }
28
+ * ```
29
+ */
30
+ type OptionalKeys<
31
+ T,
32
+ K extends keyof T
33
+ > = Omit<T, K> & Partial<Pick<T, K>>;
34
+ /**
35
+ * Deeply makes all properties readonly.
36
+ */
37
+ type DeepReadonly<T> = { readonly [P in keyof T] : T[P] extends object ? DeepReadonly<T[P]> : T[P] };
38
+ /**
39
+ * Deeply makes all properties partial (optional).
40
+ */
41
+ type DeepPartial<T> = { [P in keyof T]? : T[P] extends object ? DeepPartial<T[P]> : T[P] };
42
+ /**
43
+ * Creates a type that requires at least one of the specified keys.
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * type Props = AtLeastOne<{ a?: string; b?: number; c?: boolean }, "a" | "b">;
48
+ * // Must have at least 'a' or 'b'
49
+ * ```
50
+ */
51
+ type AtLeastOne<
52
+ T,
53
+ Keys extends keyof T = keyof T
54
+ > = Omit<T, Keys> & { [K in Keys]-? : Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>> }[Keys];
55
+ /**
56
+ * Creates a type that requires exactly one of the specified keys.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * type Auth = ExactlyOne<{ token?: string; apiKey?: string }, "token" | "apiKey">;
61
+ * // Must have exactly one of 'token' or 'apiKey', not both
62
+ * ```
63
+ */
64
+ type ExactlyOne<
65
+ T,
66
+ Keys extends keyof T = keyof T
67
+ > = Omit<T, Keys> & { [K in Keys]-? : Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, never>> }[Keys];
68
+ /**
69
+ * Extracts the element type from an array type.
70
+ */
71
+ type ElementOf<T> = T extends readonly (infer E)[] ? E : never;
72
+ /**
73
+ * Creates a union type from object values.
74
+ */
75
+ type ValueOf<T> = T[keyof T];
76
+ /**
77
+ * Makes a type's properties mutable (removes readonly).
78
+ */
79
+ type Mutable<T> = { -readonly [P in keyof T] : T[P] };
80
+ /**
81
+ * Asserts at compile time that a type is never (exhaustiveness check).
82
+ *
83
+ * @param value - The value that should be never
84
+ * @throws Error - Always throws if reached at runtime
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * type Status = "pending" | "done";
89
+ * function handle(status: Status) {
90
+ * switch (status) {
91
+ * case "pending": return "...";
92
+ * case "done": return "ok";
93
+ * default: return assertNever(status);
94
+ * }
95
+ * }
96
+ * ```
97
+ */
98
+ declare function assertNever(value: never): never;
99
+ export { assertNever, ValueOf, RequiredKeys, OptionalKeys, Mutable, ExactlyOne, ElementOf, DeepReadonly, DeepPartial, AtLeastOne };
@@ -0,0 +1,8 @@
1
+ // @bun
2
+ // packages/types/src/utilities.ts
3
+ function assertNever(value) {
4
+ throw new Error(`Unexpected value: ${JSON.stringify(value)}`);
5
+ }
6
+ export {
7
+ assertNever
8
+ };
package/package.json ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "@outfitter/types",
3
+ "description": "Branded types, type guards, and type utilities for Outfitter",
4
+ "version": "0.1.0-rc.1",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ "./deep": {
13
+ "import": {
14
+ "types": "./dist/deep.d.ts",
15
+ "default": "./dist/deep.js"
16
+ }
17
+ },
18
+ ".": {
19
+ "import": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ }
23
+ },
24
+ "./utilities": {
25
+ "import": {
26
+ "types": "./dist/utilities.d.ts",
27
+ "default": "./dist/utilities.js"
28
+ }
29
+ },
30
+ "./collections": {
31
+ "import": {
32
+ "types": "./dist/collections.d.ts",
33
+ "default": "./dist/collections.js"
34
+ }
35
+ },
36
+ "./short-id": {
37
+ "import": {
38
+ "types": "./dist/short-id.d.ts",
39
+ "default": "./dist/short-id.js"
40
+ }
41
+ },
42
+ "./hash-id": {
43
+ "import": {
44
+ "types": "./dist/hash-id.d.ts",
45
+ "default": "./dist/hash-id.js"
46
+ }
47
+ },
48
+ "./branded": {
49
+ "import": {
50
+ "types": "./dist/branded.d.ts",
51
+ "default": "./dist/branded.js"
52
+ }
53
+ },
54
+ "./guards": {
55
+ "import": {
56
+ "types": "./dist/guards.d.ts",
57
+ "default": "./dist/guards.js"
58
+ }
59
+ },
60
+ "./package.json": "./package.json"
61
+ },
62
+ "sideEffects": false,
63
+ "scripts": {
64
+ "build": "bunup --filter @outfitter/types",
65
+ "test": "bun test",
66
+ "typecheck": "tsc --noEmit",
67
+ "clean": "rm -rf dist"
68
+ },
69
+ "dependencies": {
70
+ "@outfitter/contracts": "workspace:*",
71
+ "better-result": "^2.5.0"
72
+ },
73
+ "devDependencies": {
74
+ "@types/bun": "latest",
75
+ "typescript": "^5.8.0"
76
+ },
77
+ "keywords": [
78
+ "outfitter",
79
+ "types",
80
+ "branded",
81
+ "typescript"
82
+ ],
83
+ "license": "MIT",
84
+ "repository": {
85
+ "type": "git",
86
+ "url": "https://github.com/outfitter-dev/outfitter.git",
87
+ "directory": "packages/types"
88
+ },
89
+ "publishConfig": {
90
+ "access": "public"
91
+ }
92
+ }