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

Assertions do not narrow related variables like conditions do #60904

Closed
tusharsnx opened this issue Jan 2, 2025 · 6 comments
Closed

Assertions do not narrow related variables like conditions do #60904

tusharsnx opened this issue Jan 2, 2025 · 6 comments
Labels
Not a Defect This behavior is one of several equally-correct options

Comments

@tusharsnx
Copy link

🔎 Search Terms

Assertion functions
Narrowing

🕗 Version & Regression Information

  • This changed between versions ______ and _______
  • This changed in commit or PR _______
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about _________
  • I was unable to test this on prior versions because _______

⏯ Playground Link

https://www.typescriptlang.org/play/?ssl=17&ssc=54&pln=1&pc=1#code/MYewdgzgLgBGCuBbAXHJAjApgJxgXhgEYBuAKFElgEsIA5JAeTE3zUXzwJNJ4HpeYAFQAWLAIIQIOKFXAxwAGwCecAIbZsIAO4QYAAxr1ETTHphQQMAERRs8TFYA0MdPFgLMqgG6ZdehIhmqroBWNikAGbwYMAycsFS2FCCdpgAFF6qCvao6CAgHqpgAJSoCdK6mdksNOapMADepDAwVBEwaQCEVfbF5sKaWjAAohog2GlWYCCwtvZWxWQAvqTlSSn2aYaMzIuk28bMxC0nLfwwqrHwWah6c6bHmAAeAA6YsZgAJrf3ZoCg5KQAsdTiCzgJLlBrgpbqEcHpHq93lAvrdCGYYIAZch4pHOegAkhEzGB1INdHkoMJ9AcTEEwJ99AE9Pt2l0tnQdphin0KYMRmMJlMZnV5ntqUdQTBzhCoT9UvCYM83h9vvpfjAAUCJSCpVcbvo0QilciVXo0RK-kA

💻 Code

const num: number = 1;
const isNumOne = num === 1;


// The Assertion only narrows `isNumOne` to "true", but leaves `num` as number
function assertTrue(value: boolean): asserts value is true {
  if (!value) throw Error("not true");
}
assertTrue(isNumOne);
isNumOne;       // actual: `true`; expected: `true` ✅
num;            // actual: `number`; expected: `1`  ❌


// `If` narrows both `isNumOne` and `num`
if (!(isNumOne)) throw Error("not true");
isNumOne;       // actual: `true`; expected: `true` ✅
num;            // actual: `1`; expected: `1`       ✅

🙁 Actual behavior

In the example above, when isNumOne is narrowed to true using an assertion function assertTrue() or if, I expect num to be narrowed down to 1 at the same time because they're related.

🙂 Expected behavior

This seems only true in the case of if. assertTrue() narrows only isNumOne without narrowing num.

Additional information about the issue

No response

@MartinJohns
Copy link
Contributor

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.

@tusharsnx
Copy link
Author

tusharsnx commented Jan 2, 2025

@MartinJohns Thanks for the insights.

To my understanding function assertions don't violate any of the rules from that definition. The conditional expression and the object/value are constants in this case, so they should be narrowed down, right?

@Andarist
Copy link
Contributor

Andarist commented Jan 2, 2025

It works OK with a different kind of assertion function:

function assertTrue(value: boolean): asserts value {
  if (!value) throw Error("not true");
}

The variant you have used (asserts value is true) is only used to narrow the type of the value. It doesn't try to narrow using aliased conditions. The one I mention is though and it's more natural to write it when you are looking for this kind of a logic

@RyanCavanaugh RyanCavanaugh added the Not a Defect This behavior is one of several equally-correct options label Jan 3, 2025
@tusharsnx
Copy link
Author

@Andarist That made it work. Thanks.

Just curious why doesn't asserts value is true not work? Is it too loose to help typescript narrow the indirect references?

@Andarist
Copy link
Contributor

Andarist commented Jan 3, 2025

It was designed to perform a different kind of narrowing. Only asserts condition is meant to mimic if-like behavior

@tusharsnx
Copy link
Author

I see! Can asserts value is type also be supported just like asserts value for narrowing?

I'm closing the issue since asserts value works for my use case.

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