Reputation: 3013
I have the following code block
const { att: { p, r } = {}, dir: { hdg } = {} } = record;
if ([p, r, hdg].some((e) => e === undefined)) {
return null;
}
//TS2532: Object is possibly 'undefined'.
const heading = hdg.toValue("rad");
I destructure an object and then I check if any of the properties are undefined, if any of them is I exist the function, otherwise I continue the execution.
Even after the guard clause typescript still complains the object might be undefined.
How can I write this guard clause to make the compiler happy knowing the any of the fields can be 0 or booleans, except
if (p === undefined || r === undefined || hdg === undefined) {
return null;
}
Upvotes: 0
Views: 1461
Reputation: 31815
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)
}
Upvotes: 2