-
Notifications
You must be signed in to change notification settings - Fork 12.8k
add type-guard for void
#1806
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
Comments
My impression is this is an attempt to hack in making an implementation require null checks. This probably isn't the route we'd go if we want to enable that sort of feature (which I understand the desire for). As far the unique behavior of NOTE: We might consider disallowing declaring variables of type Void as they serve no useful purpose. However, because Void is permitted as a type argument to a generic type or function it is not feasible to disallow Void properties or parameters. |
The point is not really to force null check (and in my example the typeguard that compare to undefined would not prevent us from null) but to have a better subtype than |
So how would this differ from your proposal for |
It's quite different, let me give an example: type mixed = {} | void;
function acceptMixed(arg: mixed): void {
if (typeof arg === 'string') {
arg.split(...); //valid
}
arg.hasOwnProperty('hello') // error
console.log(arg) // no error
}
acceptMixed('string') // no error
acceptMixed(3) //no error anything can be assigned to the function acceptObject(arg: object): void {
arg.hasOwnProperty('hello') // no error
}
acceptMixed('string') // error
acceptMixed(3) // error If we added type guard for 'undefined', we could narrow type to However like I said that's not something that I absolutely want, I just think that the type |
Agree there should be a nullish type guard: function accept(arg: string): void {
if (arg == null) {
// arg narrows to void
} else {
// arg narrows to string!null!undefined
arg = null // error
}
} Some related thoughts at the bottom of #1892 |
The reasoning for removing 'void' is it's already a type that is included in every union type. type uniona = string | number; // infers string|number|void
type unionb = string | number | void; // void here is *not* needed since 'string | number' -> implies string|number|void
function accept(arg: string): void {
if (arg == null) {
// arg narrows to void
} else {
// arg narrows to string!null!undefined
arg = null
}
}
function a(arg: uniona): void {
'use strict'
if (arg == null) {
// arg narrows to void
} else {
// arg narrows to string|number&!null!undefined
arg = null // error
}
}
function b(arg: unionb): void {
if (arg == null) {
// arg narrows to void
} else {
// arg narrows to string|number&!null!undefined
arg = null
}
} |
I would see this as part of nullable/non-nullable types support (#185); non-nullable types is something that we did not dismiss, but it is not on the roadmap for the short term. |
so what would be the use cases here? |
@danquirk's reply in #1806 (comment) would be my opinion as well. I do not think this is the intention of void as a type; and I have not seen compelling use cases so far. I would say the issue should be closed. |
Without a void type guard, how would you satisfy this: declare var k: (() => string)|void;
if (k !== null || k !== undefined) k();
if (typeof k !== 'undefined') k();
if (typeof k == 'Function') k(); Every attempt to invoke |
That seems like exactly the type of pattern I described in #1806 (comment) |
I think you are right, the Unlike my former example where the type can be reduced, the following (if I am not mistaken) can not be reduced because generics do not apply arguments to specialized overloads? declare function foo(name: 'bar'): (i: number) => string;
declare function foo(name: 'manchu'): (key: string) => string;
declare function foo(name: string): void;
foo('bar')(1); // no error, returns string
foo('manchu')('wok'); // no error, returns string
foo('bar')('?'); // "Arg of type string ... not a number"
foo('manchu')(1); // "Arg of type number ... not a string"
foo('?')(); // "Cannot invoke expr ... no call sig"
function factory<N extends string, T>(name: N, arg: T): string {
return foo(name)(arg); // "Cannot invoke expr ... no call sig"
} It does seem quite contrived, but I would like to be able to guarantee (at compile time) that calling |
looks like a duplicate of #3076. |
There is a type that is quite interesting in typescript
void | {}
, this type has some unique behavior, everything can be assigned to this type, but the compiler does not infer any property for this type unlike for{}
that inherits the basic object properties, the difference with{}
is subtile but still pretty interesting:However there is not typeguard for
void
, it could be interesting to add some type guards for this case:typeof val !== 'undefined'
val !== undefined
val != undefined
val != null
The text was updated successfully, but these errors were encountered: