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

TypeScript does not narrow variable that cannot be undefined #60958

Closed
AlphanumericCharacters123 opened this issue Jan 12, 2025 · 2 comments
Closed

Comments

@AlphanumericCharacters123

🔎 Search Terms

Suppose I have two variables:

let someString: string | undefined
let someMap: Map<string, number> | undefined

I use these two variables to create a third variable:

const neitherUndefined = typeof someString !== 'undefined'
    && typeof someMap !== 'undefined'

Later I attempt to access someMap:

if (neitherUndefined)
{
    someMap.get('key')
}

TypeScript will highlight this an error, saying someMap may be undefined.

I would know for a fact in this case that it is not undefined, since that is part of the neitherUndefined boolean. I could use the ! non-null assertion operator, but I don't like to do that. I could avoid using a composite boolean, and explicitly check both conditions where needed, but it's more verbose.

Is it possible to add this functionality to TypeScript without a significant compiler performance impact?

I know there are somewhat similar issues, but most of the ones I have been able to find revolve around a potentially-undefined value when used as part of bracket notation (#10530, #10565) or with the in operator (#15256). These issues were helpfully mentioned by this jcalz StackOverflow answer.

I have found similar questions on StackOverflow, such as this one, with no answers.

Since this is checking whether a variable itself is undefined, and not a property within an object or a key in bracket notation, hopefully it can be done. I have a feeling that it would have already been done if possible, though, so it's likely this has been discussed already - in which case I would appreciate being linked to the duplicate issues since I haven't been able to find them yet.

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about type narrowing.

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.0-dev.20250112#code/DYUwLgBAzg9gtiAymATgSwHYHMBc1WZYQA+EArhgCYgBmmIlAUKJLAgLICGADnl9wB4oBbABoIGMnABGIFAD4S5KrXpNGAYxgZhEkGjAALOQFUVdDAwgBeCGACe3EDBrR4SEUQCE12wHIKagsGP0YIcIgAMki7R2dXNhB+CB9-QNVLSlDGNFcACksDYxQzILUASkYAbzCIxP4AOixwPL8AaxB7P0qAXyA

💻 Code

let someString: string | undefined
let someMap: Map<string, number> | undefined

const neitherUndefined = typeof someString !== 'undefined'
    && typeof someMap !== 'undefined'

if (neitherUndefined)
{
    someMap.get('key')
}

🙁 Actual behavior

someMap.get('key') within the conditional is has the following error: 'someMap' is possibly 'undefined'.(18048).

🙂 Expected behavior

someMap.get('key') within the conditional can never be undefined.

Additional information about the issue

No response

@AlphanumericCharacters123 AlphanumericCharacters123 changed the title TypeScript does not narrow undefined variable TypeScript does not narrow variable that cannot be undefined Jan 12, 2025
@MartinJohns
Copy link
Contributor

MartinJohns commented Jan 12, 2025

Your search terms are excessive. You won't be able to find any duplicates if you write your entire issue in the search box.

This is working as intended, see #44730:

Narrowing through indirect references occurs only when the conditional expression or discriminant property access is declared in a const variable declaration with no type annotation, and the reference being narrowed is a const variable, a readonly property, or a parameter for which there are no assignments in the function body.

@AlphanumericCharacters123
Copy link
Author

@MartinJohns Thanks, that linked issue answers my question!

To clarify, I searched prior to writing the issue with various other search terms, but didn't come across this one.

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