Skip to content

Commit

Permalink
feat: add PartializedUnion
Browse files Browse the repository at this point in the history
  • Loading branch information
ashgw committed Oct 28, 2024
1 parent 47ce6f2 commit de02d84
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Checkout the full [API reference](https://ts-roids.ashgw.me/) for all usage exam

#### Types

- [`PartializedUnion<T>`](https://ts-roids.ashgw.me/types/PartializedUnion.html) - Creates a union type where each variant has its specific properties required, while other properties are optional.

- [`Prune<T,N = NotIncluded>`](https://ts-roids.ashgw.me/types/Prune.html) - Prune a type `T` by recursively omitting properties of type `N` (defaults to [`NotIncluded`](https://ts-roids.ashgw.me/types/NotIncluded.html)).
- [`DeepToPrimitive<Obj>`](https://ts-roids.ashgw.me/types/DeepToPrimitive.html) - Recursively transforms an object type T into a type where all properties are replaced with their corresponding primitive types.
- [`Assign<Obj,ObjArr>`](https://ts-roids.ashgw.me/types/Assign.html) - Copies all enumerable own properties from one target object to a source array of objects.
Expand Down Expand Up @@ -72,6 +74,8 @@ Checkout the full [API reference](https://ts-roids.ashgw.me/) for all usage exam
- [`ExcludeNull<T>`](https://ts-roids.ashgw.me/types/ExcludeNull.html) - Excludes ``null`` from a type ``T``.
- [`ExcludeNullable<T>`](https://ts-roids.ashgw.me/types/ExcludeNullable.html) - Excludes [`Nullable`](https://ts-roids.ashgw.me/types/Nullable.html) from a type ``T``.
- [`ExcludeUndefined<T>`](https://ts-roids.ashgw.me/types/ExcludeUndefined.html) - Excludes `undefined` from a type ``T``.
- [`KeysOfUnion<T>`](https://ts-roids.ashgw.me/types/KeysOfUnion.html) - Extracts the union of keys from a given union of object types, useful for accessing all possible keys in unions.
- [`Simplify<T>`](https://ts-roids.ashgw.me/types/Simplify.html) - Flattens the structure of a type by resolving intersections and simplifying nested mapped types, enhancing readability.
- [`Extends<T,U>`](https://ts-roids.ashgw.me/types/Extends.html) - Evaluates whether one type ``T`` is assignable to another type ``U``.
- [`Falsy`](https://ts-roids.ashgw.me/types/Falsy.html) - Represents a type that is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) JavaScript.
- [`FalsyProperties<T>`](https://ts-roids.ashgw.me/types/FalsyProperties.html) - Extracts falsy properties from an object type ``T``.
Expand Down
72 changes: 72 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2272,3 +2272,75 @@ export type Prune<T, N = NotIncluded> = OmitExactlyByTypeDeep<T, N>;
export type PartialExcept<T, K extends keyof T> = {
[P in K]: T[P];
} & Partial<Omit<T, K>>;

/**
* `KeysOfUnion` extracts the union of keys from a given union of object types.
* This is useful in scenarios where you need to access all possible keys across
* unioned object types within conditional or mapped types.
*
* @template T - The union of object types to extract keys from.
*
* @example
* ```ts
* type UnionKeys = KeysOfUnion<{ a: string } | { b: number }>; // Result: 'a' | 'b'
* ```
*/

type KeysOfUnion<T> = T extends T ? keyof T : never;
/**
* `Simplify<T>` flattens the structure of a given type by resolving intersections
* and reducing redundant wrapping, making complex types easier to work with.
* This type is particularly helpful for deeply nested mapped types, where
* readability and simplicity of the resulting type is crucial.
*
* @template T - The type to simplify.
*
* @example
* ```ts
* type Flattened = Simplify<{ a: string } & { b: number }>; // Result: { a: string; b: number }
* ```
*/
export type Simplify<T> = { [KeyType in Keys<T>]: T[KeyType] } & EmptyObject;

/**
* `PartializedUnion<T>` creates a union type where each member has its own properties as required,
* while properties from other members of the union are made optional and set to `undefined`.
* This is useful for cases where different configurations or variants in a union require only their specific fields.
*
* @template T - The union of object types for which partially optionalized variants should be created.
* @template AllKeys - The union of all possible keys across the union's types, derived from `KeysOfUnion`.
*
* @example
* ```ts
* type Config = PartializedUnion<
* | { dbConnectionString: string; maxConnections: number }
* | { apiEndpoint: string; apiKey: string }
* | { storageBucket: string; accessKeyId: string; secretAccessKey: string }
* >;
*
* // Example usage:
* function configureService(config: Config) {
* if (config.dbConnectionString) {
* console.log(`Configuring database with connection string ${config.dbConnectionString}`);
* } else if (config.apiEndpoint) {
* console.log(`Configuring API with endpoint ${config.apiEndpoint}`);
* } else if (config.storageBucket && config.accessKeyId && config.secretAccessKey) {
* console.log(`Configuring storage bucket ${config.storageBucket}`);
* } else {
* console.log('Invalid configuration');
* }
* }
*
* configureService({ dbConnectionString: 'postgres://...', maxConnections: 100 });
* configureService({ apiEndpoint: 'https://api.example.com', apiKey: '1234' });
* configureService({ storageBucket: 'my-bucket', accessKeyId: 'AKIA...', secretAccessKey: 'abcd' });
* ```
*/
export type PartializedUnion<
T extends object,
AllKeys extends KeysOfUnion<T> = KeysOfUnion<T>,
> = Simplify<
T extends unknown
? T & Partial<Record<Exclude<AllKeys, Keys<T>>, undefined>>
: never
>;

0 comments on commit de02d84

Please sign in to comment.