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.