Skip to content
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

Narrowing type with boolean algebra #35704

Closed
2 tasks
macabeus opened this issue Dec 16, 2019 · 7 comments
Closed
2 tasks

Narrowing type with boolean algebra #35704

macabeus opened this issue Dec 16, 2019 · 7 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@macabeus
Copy link

macabeus commented Dec 16, 2019

Search Terms

  • narrow type
  • boolean algebra

Suggestion

I know that TypeScript doesn't do any boolean algebra, but would be very nice to add support for this, even for simple operators, such as !.
With that we could write more readable and safer code.

Related:

Use Cases

Let's say that we are typing a response from an API:

type TApiResponse = {
    valid: false,
    errorMessage: string
  } |
  {
    valid: true,
    value: number
  }
}

So, if we receives a valid response, we have a value property, otherwise we'll have an errorMessage. We can check if it was successful or not checking the boolean value from valid.

So we could do it:

const result = await fetchMyApi() // I don't know if result has errorMessage or value...

if (result.valid === false) { // Let's check it...
  alert(result.errorMessage) // Nice! Narrowing for 'valid: false'
                        // now I have sure that we have result.message
  return
}

// And narrowing for 'valid: true'...
console.log(result.value) // It's woking!

But if we use some lint rule such as no-boolean-literal-compare we aren't allow to use result.valid === false, but just !result.valid, and it won't narrow, because TypeScript doesn't do any boolean algebra:

const result = await fetchMyApi()

if (!result.valid) {
  alert(result.errorMessage) // Error!! I don't know if we really have 'message' here!
  return
}

console.log(result.value) // But for some reason, we don't have any error here (I don't know why)

Checklist

My suggestion meets these guidelines:

  • Allow very simple boolean algebra, such as unary operators
  • Allow binary operation
@dragomirtitian
Copy link
Contributor

Nitpick: You need to check the items in the guidelines checklist not come up with your own check list (I would say this feature request probably checks the items in there but you should go trough them to make sure)

@jcalz
Copy link
Contributor

jcalz commented Dec 16, 2019

I can't reproduce the issue, either. The following works as I expect:

function hmm(result: TApiResponse) {
    if (!result.valid) {
        alert(result.errorMessage); // works
        return;
    }
    console.log(result.value) // works
}

Playground link

I mean, message is not the same as errorMessage... so what specifically is the issue here? Can you provide a Playground link that demonstrates it?

@macabeus
Copy link
Author

macabeus commented Dec 16, 2019

@jcalz I have this error on Visual Studio Code:

image

image

And it fails:

ERROR in /Users/macabeus/ApenasMeu/front/web/src/containers/new-order-steps/Payment/GetDiscount.tsx
./src/containers/new-order-steps/Payment/GetDiscount.tsx
[tsl] ERROR in /Users/macabeus/ApenasMeu/front/web/src/containers/new-order-steps/Payment/GetDiscount.tsx(56,38)
      TS2339: Property 'errorMessage' does not exist on type '{ valid: false; errorMessage: string; } | { valid: true; type: "percentual" | "absolut"; value: number; code: string; }'.
  Property 'errorMessage' does not exist on type '{ valid: true; type: "percentual" | "absolut"; value: number; code: string; }'.
Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = ./index.html
       4 modules
ℹ 「wdm」: Failed to compile.

And very weird... I'm trying to reproduce this same error on playground, but I can't.
Do you have any idea? I checked the TypeScript and some configs.

(also, the typo message instead of errorMessage was specifically when I was writing this issue)

@adekau
Copy link

adekau commented Dec 16, 2019

What is your workspace typescript version? (Displays bottom right of VSCode)

@macabeus
Copy link
Author

@adekau My TypeScript version is 3.7.2

@ark120202
Copy link

@macabeus it's reproducible on playground when strictNullChecks flag is disabled. That's a valid error though, because without that flag it's possible to specify valid: undefined for both states.

@DanielRosenwasser DanielRosenwasser added the Working as Intended The behavior described is the intended behavior; this is not a bug label Dec 16, 2019
@macabeus
Copy link
Author

macabeus commented Dec 16, 2019

@ark120202 Oh, thank you! I didn't know about this config. Very thank you.
Since it isn't anymore a suggestion, I'm closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

6 participants