To extract your desired object types from the Union Some
, you can utilize the Extract
method in the following way:
type Some = { field: "add" } | { field: "remove" };
declare function add(value: Extract<Some, { field: "add" }>): void;
// ^? value: { field: "add"; }
declare function remove(value: Extract<Some, { field: "remove" }>): void;
// ^? value: { field: "remove"; }
For a scenario where Some
includes additional properties like:
type Some =
| { field: "add"; property2: string }
| { field: "remove"; property2: number };
there may be unexpected properties extracted:
declare function add(value: Extract<Some, { field: "add" }>): void;
declare function remove(value: Extract<Some, { field: "remove" }>): void;
add({ field: "add" });
// ~~~~~ Property 'property2' is missing in type '{ field: "add"; }' ...
Explore more on this in the TypeScript Playground
Alternatively, you can opt for object literal types. This method is more straightforward, but it disconnects from the original union Some
, making it less resilient to future name changes in the field
property without compiler warnings.
type Some = { field: "add" } | { field: "remove" };
declare function add(value: { field: "add" }): void;
// ^? value: { field: "add"; }
declare function remove(value: { field: "remove" }): void;
// ^? value: { field: "remove"; }
While the object literal approach is simpler, I personally find it more error-prone compared to using Extract
.