Is there a method to create a TypeScript typeguard for a complex combinatory type that includes multiple "and" and "or" statements to check for the presence of one of the "or" types?
For example:
interface Type1 { cat: string }
interface Type2 { dog: boolean }
interface Type3 { mouse: number }
interface Type4 { elephant: string | number }
type CombinatoryType = (Type1 & (Type2 | Type3)) | Type4;
If we have typeguards to verify the existence of Type2 and Type4 (named hasType2
and hasType4
respectively), calling them in a specific order should yield certain results:
function doSomething(data: CombinatoryType) {
if (hasType2(data)) {
// 'data' now has type: (Type1 & Type2) | Type4
if (hasType4(data)) {
// 'data' is now of type: Type1 & Type2 & Type4
}
}
}
And calling them in reverse order should produce different outcomes:
function doSomething(data: CombinatoryType) {
if (hasType4(data)) {
// 'data' is now of type: (Type1 & (Type2 | Type3)) & Type4
if (hasType2(data)) {
// 'data' now holds type: Type1 & Type2 & Type4
}
}
}
Key points to consider:
- The typeguard must retain previous type information without losing it due to prior assertions.
- Avoid setting an explicit return type like
data is (Type1 & Type2) | Type4
as the combinatory type could become extensive, potentially causing issues with VSCode's type inference (although intellisense remains functional).