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.
