Home > front end >  type operator for removing from a tagged union
type operator for removing from a tagged union

Time:02-10

Is it possible to remove a specific type literal from a tagged union / discriminated union? How would I write such a type?

Given this type:

type MyUnion = {
  kind: "foo"
  foo: number
} | {
  kind: "bar"
  bar: string
} | {
  kind: "baz"
  baz: boolean
}

I want to remove the {kind: "baz", baz: boolean} type literal. Is it possible to write a type RemoveTag<T, K, V> such that:

type MyUnionWithoutBaz = RemoveTag<MyUnion, "kind", "baz">

yields:

type MyUnionWithoutBaz = {
  kind: "foo"
  foo: number
} | {
  kind: "bar"
  bar: string
}

?

CodePudding user response:

You can use the Exclude<T, U> utility type to filter members from out a union T which are not assignable to another type U. Your RemoveTag type could therefore be written as

type RemoveTag<T, K extends keyof T, V> =
  Exclude<T, Record<K, V>>

depending on your use cases (if the discriminant property is optional then it wouldn't work as is). For your example, it produces:

type MyUnionWithoutBaz = RemoveTag<MyUnion, "kind", "baz">
/* type TWithoutBaz = {
    kind: "foo";
    foo: number;
} | {
    kind: "bar";
    bar: string;
} */

as desired.

Playground link to code

  • Related