-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestion: warn on always-false typeguards #34936
Comments
declare const x: string;
declare function isString(x: unknown): x is string;
if (!isString(x)) {
//`x` is now of type `never`
//but I want this to compile
//because defensive programming against JS code
throw new Error(`Expected string; received ${typeof x}`);
} |
@AnyhowStep He mentioned that, actually.
|
I don't think it's justifiable that defensive checks are always written in always-true format. You could easily imagine writing: function fn(x: number) {
if (isNullOrUndefined(x)) Debug.fail("x must be provided");
} It's not clear what distinguishes this from the case in the OP. |
That's a good point, though I suspect it's a much less common case. There's always the option to cast to unknown, though it's not particularly satisfying. It's also less relevant for this to be a type guard, since it's not actually narrowing anything. @RyanCavanaugh - my underlying motivation was a comment you made about wanting to warn on Maybe a cleverer approach would be to warn if |
I suppose one could declare the check as declare function isNullOrUndefined(x: any): x is null | undefined; But that doesn't seem useful; when do you ever need a value that's guaranteed to be nullish? And if you're not using it as a type guard... well, then that's what distinguishes it from the OP. The issue is about warning on always-false type predicate calls. I can't think of a single time I've ever seen a type guard which is expected to always be false in normal operation. Generic defensive |
Search Terms
type guard always-false warning
Suggestion
When a typeguard is always false, the guarded variable is type
never
within the body. While you can't actually look up any properties onnever
, you can pass it anywhere or assign it to anything and there's absolutely no warnings. Calling a typeguard function with an argument that has no overlap with the guard should produce a warning.Use Cases
My immediate motivation is #24436 (comment), where if
Number.isFinite
could be written as a typeguard (this would also need a narrowernumber
subtype, see e.g. #32188) then it could easily be allowed to be called with anumber|string
, but no additional gymnastics would be required to warn if calling with a guaranteed non-number
.In general there's not a good reason to call an always-false typeguard. This is quite different from the always-true case where defensive coding comes into play.
Examples
Example:
If
usePrivate
requires a private type that this scope doesn't have access to construct, then it would be nice if this code warned somewhere. Instead, it currently just narrowsx
tonever
and allows doing whatever you want with it.Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: