Created
August 9, 2019 18:16
-
-
Save OliverJAsh/a6de628277b424573bee28a431182c79 to your computer and use it in GitHub Desktop.
A negate function for type guards
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type TypeGuard<T, U extends T> = (value: T) => value is U; | |
const negate = <T, U extends T>( | |
typeGuard: TypeGuard<T, U>, | |
): TypeGuard<T, Exclude<T, U>> => (value): value is Exclude<T, U> => | |
typeGuard(value) === false; | |
// Example | |
const checkIsArray = <T>(value: T | any[]): value is any[] => | |
Array.isArray(value); | |
const checkIsNotArray = negate(checkIsArray); | |
declare const value: string | string[]; | |
if (checkIsNotArray(value)) { | |
value; // type here is `string` 🎉 | |
} |
I think the issue there is that types cannot be excluded from unknown
(in this case, Exclude<unknown, string> => unknown
).
If you don't use unknown
, it works:
declare function isString(candidate: string | number): candidate is string;
… but I guess that's not always an option! I guess Exclude
only works for filtering union types, so the parameter has to be a union.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note:
negate
can only work if the input type guard is generic. It won't work in situations like this: