Skip to content

Instantly share code, notes, and snippets.

@virtuallyunknown
Created June 26, 2023 00:41
Show Gist options
  • Save virtuallyunknown/252bda9b972684df2c08daaadce37ff0 to your computer and use it in GitHub Desktop.
Save virtuallyunknown/252bda9b972684df2c08daaadce37ff0 to your computer and use it in GitHub Desktop.
TS: Recursively filter out branches of an array of items (by set criterion)
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
const commands = [
{
name: 'foo',
options: [
{ name: 'foo-string', type: 'STRING', autocomplete: true },
{ name: 'foo-integer', type: 'INTEGER' },
],
},
{
name: 'bar',
options: [
{
name: 'bar-subcommand-1',
type: 'SUBCOMMAND',
options: [
{ name: 'bar-string', type: 'STRING', autocomplete: true },
{ name: 'bar-integer', type: 'INTEGER' },
],
},
{
name: 'bar-subcommand-2',
type: 'SUBCOMMAND',
options: [
{ name: 'bar-string', type: 'STRING' },
{ name: 'bar-integer', type: 'INTEGER' },
],
},
],
},
{
name: 'baz',
options: [
{
name: 'baz-subgroup-1',
type: 'GROUP',
options: [
{
name: 'baz-subgroup-subcommand',
type: 'SUBCOMMAND',
options: [
{ name: 'baz-string', type: 'STRING', autocomplete: true },
{ name: 'baz-integer', type: 'INTEGER', autocomplete: true },
],
},
],
},
{
name: 'baz-subcommand-1',
type: 'SUBCOMMAND',
options: [
{ name: 'baz-string', type: 'STRING', autocomplete: false },
{ name: 'baz-integer', type: 'INTEGER' },
],
},
],
},
{
name: 'qux',
options: []
}
] as const;
type FilterOptionNoNever<T> = T extends { options: readonly never[] } ? never : T;
type FilterOption<T> = T extends { readonly autocomplete: true }
? T
: T extends { options: infer U extends readonly any[] }
? FilterOptionNoNever<Expand<Omit<T, 'options'> & { options: FilterCommand<U> }>>
: never;
type FilterCommand<T extends readonly any[]> = {
[K in keyof T]: FilterOption<T[K]>;
};
type Foo = FilterCommand<typeof commands>[0];
type Bar = FilterCommand<typeof commands>[1];
type Baz = FilterCommand<typeof commands>[2];
type Qux = FilterCommand<typeof commands>[3];
type AllCommands = FilterCommand<typeof commands>;
@virtuallyunknown
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment