Skip to content

Commit 226ce1a

Browse files
committed
chore(package): bump version to 1.0.20
feat(docs): add Optional type for conditional key requirements in objects
1 parent 3b8df28 commit 226ce1a

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nasriya/atomix",
3-
"version": "1.0.19",
3+
"version": "1.0.20",
44
"description": "Composable helper functions for building reliable systems",
55
"keywords": [
66
"networking",

src/docs/docs.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,52 @@ export type LooseToStrict<T> = T extends any ? (string extends T ? never : T) :
219219
*/
220220
export type RequiredStrict<T> = {
221221
[P in keyof T]-?: Exclude<T[P], undefined>;
222-
};
222+
};
223+
224+
/**
225+
* Creates a new type from `T` where:
226+
* - Keys **included** in the union `I` are kept **required** (if they are).
227+
* - Keys **not included** in `I` become **optional** (i.e., the key may be omitted).
228+
* - If `I` is not provided (defaults to `never`), **all keys become optional**.
229+
*
230+
* ⚠️ Unlike `Partial<T>`, this utility makes **only the key optional**, not the value.
231+
* That means you can omit the property entirely, but you **cannot explicitly assign `undefined`**
232+
* unless `undefined` is already part of the value type.
233+
*
234+
* @template T The original object type.
235+
* @template I A union of keys from `T` that should remain required. Defaults to `never`.
236+
*
237+
* @example
238+
* type User = {
239+
* id: string;
240+
* name: string;
241+
* email: string;
242+
* };
243+
*
244+
* type WithId = Optional<User, 'id'>;
245+
* // Equivalent to:
246+
* // {
247+
* // id: string;
248+
* // name?: string;
249+
* // email?: string;
250+
* // }
251+
*
252+
* const u1: WithId = { id: '123' }; // ✅ valid
253+
* const u2: WithId = { id: '123', name: undefined }; // ❌ invalid unless `name: string | undefined`
254+
*
255+
* type AllOptional = Optional<User>;
256+
* // {
257+
* // id?: string;
258+
* // name?: string;
259+
* // email?: string;
260+
* // }
261+
*
262+
* @since 1.0.20
263+
*/
264+
export type Optional<T, I extends keyof T = never> = Prettify<
265+
{
266+
[P in keyof T as P extends I ? P : never]: T[P]; // Keep keys in `I` as-is
267+
} & {
268+
[P in keyof T as P extends I ? never : P]?: T[P]; // Optionalize keys not in `I`
269+
}
270+
>;

0 commit comments

Comments
 (0)