This type:
type T = NonNullable<GroupQuery['group']>['criterions'][0]`
Would be resolved to this type:
type T = {
__typename?: "kindA" | undefined;
id: number;
name: string;
} | {
__typename?: "kindB" | undefined;
id: number;
name: string;
}
So what you are really asking how to get the branch of the union where:
__typename === 'kindB'
In that case you can use an intersection &
to filter a union type. In general that works like this:
type T = ("A" | "B" | "C") & "A" // "A"
Playground
So you can use an intersection to make the union resolve to only the type that could match the intersected type.
type KindB =
NonNullable<GroupQuery['group']>['criterions'][0] & { __typename: 'kindB' }
Now KindB
resolves to this type:
type KindB = {
__typename?: "kindB" | undefined;
id: number;
name: string;
} & {
__typename: 'kindB';
}
As you can see, the kindA
member of the union is no longer present, and the remaining member of the union is being intersected with { __typename: 'kindB' }
. If you apply that intersection, it reduces to:
type KindB = {
__typename: "kindB";
id: number;
name: string;
}
Playground with working code
With some refactoring, you could even make this quite nice with a nice generic type alias:
// Union of all criterion types
type GroupQueryCriterions =
NonNullable<GroupQuery['group']>['criterions'][number]
// Get the branch of the criterions union that has a specific typename.
type GroupQueryCriterionType<T extends GroupQueryCriterions['__typename']> =
GroupQueryCriterions & { __typename: T }
// Get a specific criterion type.
type KindB = GroupQueryCriterionType<'kindB'>
Playground