From 9727bbac66713e45ee05c189c42222b5e246d60a Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Fri, 29 Mar 2024 16:31:39 -0700 Subject: [PATCH] Document type helpers for oneOfs (#1023) Add a section to the documentation that shows some TypeScript types that could be useful in working with union-style oneOfs. I've written these a few times in different projects so I could properly type helper functions that operate on generated oneOfs, and I figured it might be useful to other users of ts-proto. As an example, given the following: ```ts interface MusicPlayerRequest { command?: | { $case: "start"; start: StartCommand } | { $case: "stop"; stop: StopCommand } | { $case: "next"; list: NextCommand } | undefined; } ``` Then the helpers can be used like this: ```ts type MusicPlayerCommandNames = OneOfCases; // = "start" | "stop" | "next" type MusicPlayerCommands = OneOfValues; // = StartCommand | StopCommand | NextCommand type NextCommandByName = OneOfCase // = NextCommand function sendCommand( commandName: MusicPlayerCommandNames, command: OneOfCase ) { ... } // The `command` argument is automatically of type NextCommand because the `commandName` argument is "next" sendCommand("next", { skip: 1 }) ``` --- README.markdown | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.markdown b/README.markdown index 10e7f4780..7e811efe7 100644 --- a/README.markdown +++ b/README.markdown @@ -724,6 +724,28 @@ As this will automatically enforce only one of `field_a` or `field_b` "being set In ts-proto's currently-unscheduled 2.x release, `oneof=unions` will become the default behavior. +## OneOf Type Helpers + +The following helper types may make it easier to work with the types generated from `oneof=unions`: + +```ts +/** Extracts all the case names from a oneOf field. */ +type OneOfCases = T extends { $case: infer U extends string } ? U : never; + +/** Extracts a union of all the value types from a oneOf field */ +type OneOfValues = T extends { $case: infer U extends string; [key: string]: unknown } + ? T[U] + : never; + +/** Extracts the specific type of a oneOf case based on its field name */ +type OneOfCase> = T extends { + $case: infer U extends K; + [key: string]: unknown; +} + ? T[U] + : never; +``` + # Default values and unset fields In core Protobuf (and so also `ts-proto`), values that are _unset_ or equal to the default value are not sent over the wire.