I have a case where I'm frequently checking both the value of a boolean and another union type together. While they're logically connected and could hypothetically just check one, I need to check both so the TS compiler knows both types.
let multiple: boolean
let value: Array<string> | string
...
if (multiple && isArray(value)) {
// TS knows multiple === true and value is an Array
}
Is there a way to write a type checking function where the type predicate asserts multiple values?
Something like this:
// Not valid Typescript
function isMulti (
multi: boolean,
value: Array<string> | string
): (multi is true) && (value is Array<string>) {
return multi && isArray(value)
}
In most cases I can get by with just checking isArray
, but there are cases where I want to reuse a check like the one above. Is this possible?
In response to @kaya3:
To give a more accurate use case, I have something similar to the following:
I could assign multiple
and value
to an object with a DiscriminatedUnion type, but that adds more complexity than I think this needs.
type ValueType<M extends boolean> = M extends true ? Array<string> : string;
interface PropTypes<M extends boolean> {
multiple: M,
// more properties
}
type DiscriminatedUnion = {
multiple: true,
value: Array<string>
} | {
multiple: false,
value: string
}
function myFunction<M extends boolean>({
multiple
}: PropTypes<M>) {
let value: ValueType<M>;
// ... later
if (multiple) {
// TS will not assert the type of `value` here
}
// Trying discriminated union
// TS Error: Type '{ multiple: boolean; value: string | string[]; }' is not assignable to type '{ multiple: false; value: string; }'
let obj: DiscriminatedUnion = {
multiple,
value
}
}