В продолжение этого ответа я пытаюсь написать общий тип, который сопоставляет тег с типом, который является частью размеченный союз.
Общая версия, указанная в ответе выше, работает:
type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = T extends Record<K, V> ? T : never
Но я не могу создать свою собственную версию, отличную от T
(самого союза). Это работает, если я сделаю тип объединения универсальным со значением по умолчанию, что я нахожу странным.
Вот мой код:
interface TypeA {
tag: "a";
data: string;
}
interface TypeB {
tag: "b";
data: [number];
}
interface TypeCD {
tag: "c" | "d";
data: number;
}
type Union = TypeA | TypeB | TypeCD;
type DiscriminatedUnion_0<V extends Union["tag"]> = Union extends Record<"tag", V> ? Union : never;
let shouldBeTypeA_0: DiscriminatedUnion_0<"a">; // doesn't work, type 'never'
// this works
type DiscriminatedUnion_1<V extends Union["tag"], T extends Union = Union> = T extends Record<"tag", V> ? T : never;
let shouldBeTypeA_1: DiscriminatedUnion_1<"a">;
type DiscriminatedUnion_2<V extends Union["tag"], T extends Union> = T extends Record<"tag", V> ? T : never;
let shouldBeTypeA_2: DiscriminatedUnion_2<"a", Union>;