Skip to content

fix: Error for problematic type assertions#63

Merged
acutmore merged 4 commits into
mainfrom
issue-62
May 12, 2026
Merged

fix: Error for problematic type assertions#63
acutmore merged 4 commits into
mainfrom
issue-62

Conversation

@acutmore

Copy link
Copy Markdown
Collaborator

Issue number of the reported bug or feature request: #62

Describe your changes
This PR adds new logic to emit an error when a type assertion can not be safely erased.

Testing performed
New test fixtures for both good and bad cases have been added.

Additional context
It would be simpler to not take the operator precedence into account and to always error instead, forcing the author to always use explicit parenthesis when mixing type assertion operators within binary expressions. This felt too restrictive and adding operator precedence checks is not too complex.

Signed-off-by: Ashley Claymore <aclaymore@bloomberg.net>

@tchetwin tchetwin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfinished review, nits/questions only

Would appreciate some more inline comments of the syntactical structures involves in functions like hasUnsafeNullishLogicalMix

Comment thread README.md
Comment thread tests/errors.test.ts Outdated
const tsInput = `1 + 1 as unknown /* comment */ / 2`;
const jsOutput = tsBlankSpace(tsInput, onError);
assert.equal(onError.mock.callCount(), 1);
assert.equal(jsOutput, tsInput);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turbo-nit: in the other fixtures the tsInput variable is not reused, the input is duplicated

Comment thread docs/unsupported_syntax.md
Comment thread src/index.ts
Comment on lines +388 to +390
if (!tslib.isBinaryExpression(baseExpr)) {
return false;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to consider the ternary operator?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to consider the case where the base is a ternary because:

true ? a : b as number / 2

Is parsed as:

true ? a : (b as number / 2);

Not:

(true ? a : b as number) / 2;

So removing the as number does not change how the expression is parsed.

For the ternary to be the base it would of had to be written as:

(true ? a : b) as number / 2

Where as number is still safe to erase.


// Other safe targeted cases:
1 * 1 as unknown + 2;
1 ?? 1 as unknown || 2;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not safe; both TypeScript and the JavaScript engine require parentheses.
Because the input code already throws an error, I’m not sure whether this complies with the garbage in, garbage out principle.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"I’m not sure whether this complies with the garbage in, garbage out principle."

Exactly that. There are existing cases in ts-blank-space where the emitted code is invalid, but that's because the input was invalid in the first place.

That said, I'll update this fixture as this fixture should only be testing valid inputs. Thanks for catching.

Comment thread tests/errors.test.ts

it("errors on `as` expression that would change operator precedence", () => {
const onError = mock.fn();
const tsInput = `1+1 as T / 2`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is another case,

1 + 1 as const / 2;

Although it looks like a type assertion (as T), it is actually a const assertion.
The TypeScript compiler reports a type error, but the underlying codegen can still produce valid JavaScript by adding parentheses to ensure the correct order of operations.

It is unclear whether this case should be handled explicitly.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I've added logic in 71ffc11 so that this is a build error too.

Signed-off-by: Ashley Claymore <aclaymore@bloomberg.net>
Signed-off-by: Ashley Claymore <aclaymore@bloomberg.net>
Signed-off-by: Ashley Claymore <aclaymore@bloomberg.net>
@acutmore acutmore merged commit 74579ce into main May 12, 2026
2 checks passed
@acutmore acutmore deleted the issue-62 branch May 12, 2026 11:51
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

Successfully merging this pull request may close these issues.

4 participants