Skip to content

Detect unreachable code in more scenarios #39995

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

Open
4 of 5 tasks
tom-sherman opened this issue Aug 11, 2020 · 10 comments
Open
4 of 5 tasks

Detect unreachable code in more scenarios #39995

tom-sherman opened this issue Aug 11, 2020 · 10 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@tom-sherman
Copy link

tom-sherman commented Aug 11, 2020

Search Terms

logical assignment binary expression dead never truthy falsy

Suggestion

Raise compiler errors when the left side of an expression using a logical operator (&& or ||) is unrechable.

Also detect unreachable branches of ternary expressions.

Use Cases

Code that is statically verifiable to be unreahable is almost always a programmer error so TypeScript should detect unreachable code in more scenarios.

Examples

declare const truthy: true
declare const falsy: false;
declare function doSomething(): number

const a = true ? 5 : doSomething(); // error: doSomething is unreachable
const b = truthy ? 5 : doSomething(); // error: doSomething is unreachable

const c = false ? doSomething() : 5; // error: doSomething is unreachable
const d = falsy ? doSomething() : 5; // error: doSomething is unreachable

if (!truthy) {
    doSomething(); // error: doSomething is unreachable
}

if (falsy) {
    doSomething(); // error: doSomething is unreachable
}

Playground link.


It would also be nice to expand unreachable code checks to other expressions that are known to be truthy or falsy eg. object/array literals, NaN eg.

declare function doSomething(): number

const a = [1,2,3] || doSomething() // error: doSomething is unreachable
const b = { count: 1 } && doSomething() // error: doSomething is unreachable

if ([1,2,3]) {
    doSomething() // error: doSomething is unreachable
}

if ({ count: 1 }) {
    doSomething() // error: doSomething is unreachable
}

Playground link.


Finally, detecting unreachable branches of a ternary expression

declare const truthy: true
declare const falsy: false;
declare function doSomething(): number

const a = true ? 5 : doSomething(); // error: doSomething is unreachable
const b = truthy ? 5 : doSomething(); // error: doSomething is unreachable

const c = false ? doSomething() : 5; // error: doSomething is unreachable
const d = falsy ? doSomething() : 5; // error: doSomething is unreachable

Playground link

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

This wouldn't be a breaking change in existing TypeScript/JavaScript code

There would be new type errors. The extra safety could be opted into by extending the allowUnreachableCode flag or creating a new flag.

@tadhgmister
Copy link

believe this is by design although I can't comment on what the intent is, see https://www.staging-typescript.org/tsconfig#allowUnreachableCode

This does not affect errors on the basis of code which appears to be unreachable due to type analysis.

@tom-sherman
Copy link
Author

I would say that these unreachable branches of logical operators fall under the category of, quote from the docs

unreachable due to the use of JavaScript syntax

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Sep 3, 2020
@RyanCavanaugh
Copy link
Member

Some use cases that aren't just code no one would reasonably write (e.g. true ? x : y or its equivalents) would be nice to give this some motivation. Operating on values that are known to be exactly true or false is relatively rare.

@tom-sherman
Copy link
Author

@RyanCavanaugh I agree that some of these may not be too useful, but others where TypeScript knows that the value is truthy (objects, mostly) I think are helpful.

[] || doSomething() I think it's really common for TypeScript to infer the LHS is truthy.

@marcandre
Copy link

Related: the nullish operator offers other further occasion to detect errors, as I mention in #43040

@jguddas
Copy link

jguddas commented Dec 16, 2021

Operating on values that are known to be exactly true or false is relatively rare.
- @RyanCavanaugh

It still happens, I just had this scenario:

export default (foo?: 'string') => {
  if (foo) {
    return 'foo'
  } else {
    return foo ? "I'm unreachable" :  'bar'
  }
}

palyground

besides not resulting in an unreachable code error, it also has a wrong return type "foo" | "I'm unreachable" | "bar" rather than "foo" | "bar"

@kermanx
Copy link

kermanx commented Aug 17, 2023

I think this feature is especially useful when working with some frameworks.

In some ImGUI frameworks, an event listener is like this:

// _.button: (text: string) => boolean
if(_.button("Click me")){
  button is clicked, now do something;
}

// _.span: (text: string) => false
if(_.span("Hello")){
  mistake; // this line should be marked as unreachable, to indicate this is a mistake.
}

@RyanCavanaugh
Copy link
Member

What framework has methods that are hardcoded to return false ? They can be annotated as : void and cause a type error to occur instead -- that seems much more useful

@kermanx
Copy link

kermanx commented Aug 18, 2023

What framework has methods that are hardcoded to return false ? They can be annotated as : void and cause a type error to occur instead -- that seems much more useful

I completely agree with you. However, I want to ensure that the return type of components is consistent – and perhaps the cost of detecting the literal falsy condition of an if-statement is very low?

@kermanx
Copy link

kermanx commented Aug 18, 2023

related issue: #45267

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants