Combine user-defined type guards / type predicates as unions and intersections.
import { isSome, isEvery } from 'combine-type-predicates';
type Foo = { foo: boolean; baz: number };
type Bar = { bar: symbol; baz: string };
const isFoo = (v: unknown): v is Foo
=> typeof v.foo === 'boolean' && typeof v.baz === 'number';
const isBar = (v: unknown): v is Bar
=> typeof v.bar === 'symbol' && typeof v.baz === 'string';
const isFooOrBar = isSome(isFoo, isBar);
// => (subject: unknown) => subject is Foo | Bar
const isFooAndBar = isEvery(isFoo, isBar);
// => (subject: unknown) => subject is Foo & Bar
const x: unknown = undefined;
if (isFooOrBar(x)) {
x.baz; // => string | number
if ('foo' in x) {
x.foo; // => boolean
} else {
x.bar; // => symbol
}
}
if (isFooAndBar(x)) {
x.foo; // => boolean
x.bar; // => symbol
x.baz; // => never (no such thing as `string & number`)
}