The best thing you could do is to use an Array
and a type predicate like this:
type SomeType = { toValue(s: string): unknown };
function test(p?: SomeType, r?: SomeType, hdg?: SomeType) {
const toCheck = [p, r, hdg];
if (checkForNulls(toCheck)) {
const [p, r, hdg] = toCheck;
const heading = hdg.toValue("rad");
}
}
function checkForNulls<T>(args: (undefined | T)[]): args is T[] {
return args.every(e => e !== undefined)
}
One downside of this solution is that it widens every Array
item type to an union type of all the actual items so it only works when the variables to check are of the same type. Otherwise the original types are lost.
Here is another solution that allows to recover original types. It works with function overload and tuples, but it requires to write as many overloads as needed usages:
type SomeType = { toValue(s: string): unknown };
function test(p?: boolean, r?: number, hdg?: SomeType) {
const toCheck = [p, r, hdg] as const;
if (checkForNulls(toCheck)) {
const [p, r, hdg] = toCheck;
const heading = hdg.toValue("rad");
}
}
function checkForNulls<T>(args: readonly [T | undefined]): args is [T]
function checkForNulls<T, U>(args: readonly [T | undefined, U | undefined]): args is [T, U]
function checkForNulls<T, U, V>(args: readonly [T | undefined, U | undefined, V | undefined]): args is [T, U, V]
function checkForNulls<T>(args: readonly (undefined | T)[]): args is T[] {
return args.every(e => e !== undefined)
}
CLICK HERE to find out more related problems solutions.