Skip to content

Ternary branches not checked #61578

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
00001H opened this issue Apr 14, 2025 · 3 comments
Closed

Ternary branches not checked #61578

00001H opened this issue Apr 14, 2025 · 3 comments
Labels
Not a Defect This behavior is one of several equally-correct options

Comments

@00001H
Copy link

00001H commented Apr 14, 2025

πŸ”Ž Search Terms

"ternary" "ts2322"

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.0-dev.20250414#code/GYVwdgxgLglg9mABAZwBZxAGwCYH0BGAprsDGIQBQCCAXImCALZEBOiAPvVpgDSIBCdBs0JtODTJgCUQpqwDeAKEQrEMYBUTVEAXj1dJUxAH4t-RAEJ9E6YjoVzenYipGpS1Z8QtCUECyR+AG5lVQBfUJUfPwDEAAYQsKA

πŸ’» Code

function should_be_fine(A: number | null, B: number | null): number{
    if( (A === null) ? (B !== null) : (B === A) ){
        return B; // <-- error here
    }
    return 0;
}

πŸ™ Actual behavior

I got a 2322 on the return B; line, saying that B is of type number | null which is not compatible with the return type number.

πŸ™‚ Expected behavior

It's obvious that B cannot be null: Depending on the ternary branch, either B !== null or B === A && A !== null must be true. Therefore, the B in return B; should have number type and the statement should compile without error.

Additional information about the issue

Replacing the if condition with (B !== null) || (B === A && A !== null) fails with the same error. In fact

function should_be_even_finer(A: number | null, B: number | null): number{
    if( true ? (B !== null) : (B !== null) ){
        return B;
    }
    return 0;
}

is the weakest form that still fails to compile, and might be a good starting point. (it reveals that ternaries are under-checked; at the very least, exprA ? exprB : exprC should imply exprA && exprB || !exprA && exprC)

@00001H 00001H changed the title Ternary Ternary branches not checked Apr 14, 2025
@MartinJohns
Copy link
Contributor

Same as: #48536 (comment)

Type narrowing is done only at the level of individual variables, not entire expressions.

@RyanCavanaugh
Copy link
Member

It's obvious that B cannot be null: Depending on the ternary branch, either B !== null or B === A && A !== null must be true. Therefore, the B in return B; should have number type and the statement should compile without error.

Type narrowing is not implemented as a constraint solver or theorem prover; it would be much too slow to try to analyze it this way. Cases where "real" code would benefit from this are few and far between.

@RyanCavanaugh RyanCavanaugh added the Not a Defect This behavior is one of several equally-correct options label Apr 16, 2025
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Not a Defect This behavior is one of several equally-correct options
Projects
None yet
Development

No branches or pull requests

4 participants