Skip to content

NonNullable should consider the void type #36703

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

Closed
amitport opened this issue Feb 9, 2020 · 5 comments
Closed

NonNullable should consider the void type #36703

amitport opened this issue Feb 9, 2020 · 5 comments

Comments

@amitport
Copy link

amitport commented Feb 9, 2020

TypeScript Version: 3.7.5

Search Terms: NonNullable void

Code

    function isNonNull<T>(value: T): value is NonNullable<T> {
      return value != null;
    }
    function test(): void | true {
      if (Math.random() < 5) {return true;}
    }
    const t1 = test();
    let t2: true;
    if (isNonNull(t1)) {
      t2 = t1;
    }

Expected behavior:
should work fine, because != null is also not void

Actual behavior:
getting Type 'void' is not assignable to type 'true'.

workaround
I'm using

type NonNullable2<T> = T extends null | undefined | void ? never : T;

which works fine

@MartinJohns
Copy link
Contributor

void does not mean "no value", it means "this value should not be used for anything". It may very well null or undefined, it may also be an object. It can be truthy or falsy.

@amitport
Copy link
Author

amitport commented Feb 9, 2020

@MartinJohns
according to typescript's doc void is just undefined | null see https://www.typescriptlang.org/docs/handbook/basic-types.html#void

If there is some other definition then IMO, this is a bug in the documentation
and how would you check if something is not void? and what is the typescript "way" of doing what I did in the example code? (how would you define the return type of a function that may implicitly returns undefined and then type guard a specific returned value)

@MartinJohns
Copy link
Contributor

MartinJohns commented Feb 9, 2020

according to typescript doc void is just undefined | null see

I'm not sure where you get this from. The documentation you linked states:

void is a little like the opposite of any: the absence of having any type at all.

Absence of having a type means it can be any value, not just undefined and null.

This FAQ section is relevant: https://github.com/microsoft/TypeScript/wiki/FAQ#why-are-functions-returning-non-void-assignable-to-function-returning-void

#35236 and #35850 have a lot of discussions regarding this behavior as well and mentions why something like void | true doesn't make sense. If you expect undefined or null, then you should type it so instead of using void.


With a small adjustment of your code the issue should become more clear:

function test(fallback: () => void): void | true {
  if (Math.random() < 5) { return true; }
  return fallback();
}

const t1 = test(() => "abc");

The type of the else-branch is void, but it will return the value "abc". This is completely legal TypeScript code.


(how would you define the return type of a function that may implicitly returns undefined and then type guard a specific returned value)

By using the appropriate type: undefined | true.

@amitport
Copy link
Author

amitport commented Feb 9, 2020

the problem is that using undefined generates TS7030: Not all code paths return a value.

@amitport
Copy link
Author

amitport commented Feb 9, 2020

I guess this is controlled by noImplicitReturns
dup #18319
closing this. thanks, @MartinJohns !

@amitport amitport closed this as completed Feb 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants