Finding
When a chained assertion is wrapped in parentheses — such as (value as unknown) as any — the detector does not classify it as unsafe_double_type_assertion. Instead it falls through to the generic single-assertion branch (or produces a different finding), because the outer AsExpression.expression is a ParenthesizedExpression, not an AsExpression.
Evidence
Reported by CodeRabbit review on PR #24 (commit 3a9b942): the visitor checks ts.isAsExpression(node.expression) which fails for parenthesized chains.
// This pattern is NOT detected as a chained assertion:
const x = (value as unknown) as any;
// AST: AsExpression → ParenthesizedExpression → AsExpression
Removing the parentheses makes it detectable:
// This pattern IS detected as a chained assertion:
const x = value as unknown as any;
Requirements
(value as X) as Y must be classified as unsafe_double_type_assertion with assertionForm: chained_as.
(value as X) as any must produce both unsafe_double_type_assertion and unsafe_type_assertion independently.
((value as X) as Y) as Z (nested parens) must still be detected.
- Non-chained parenthesized expressions must not be affected.
- Existing chain-count tests must continue to pass.
Constraints
- Do not change finding types or severity.
- Do not affect non-chained single assertions.
- Do not modify suppression behavior.
- Do not exceed the existing per-AST-node finding-count semantics.
- Do not add dependencies.
Validation
Add tests (RED before fix, GREEN after) for:
(value as X) as Y → 1 finding, unsafe_double_type_assertion
(value as unknown) as any → 2 findings (double + any)
((value as X) as Y) as Z → 2 findings
(value) as any (unnecessary parens around expression, not chain) → 1 finding unsafe_type_assertion
(value as X) as Y as Z → 2 findings (outer chain + inner chain)
- Existing 1-chain, 2-chain, 3-chain, 4-chain tests unchanged
Rollback
A reverted commit restores current parenthesized detection behavior.
Finding
When a chained assertion is wrapped in parentheses — such as
(value as unknown) as any— the detector does not classify it asunsafe_double_type_assertion. Instead it falls through to the generic single-assertion branch (or produces a different finding), because the outerAsExpression.expressionis aParenthesizedExpression, not anAsExpression.Evidence
Reported by CodeRabbit review on PR #24 (commit 3a9b942): the visitor checks
ts.isAsExpression(node.expression)which fails for parenthesized chains.Removing the parentheses makes it detectable:
Requirements
(value as X) as Ymust be classified asunsafe_double_type_assertionwithassertionForm: chained_as.(value as X) as anymust produce bothunsafe_double_type_assertionandunsafe_type_assertionindependently.((value as X) as Y) as Z(nested parens) must still be detected.Constraints
Validation
Add tests (RED before fix, GREEN after) for:
(value as X) as Y→ 1 finding,unsafe_double_type_assertion(value as unknown) as any→ 2 findings (double + any)((value as X) as Y) as Z→ 2 findings(value) as any(unnecessary parens around expression, not chain) → 1 findingunsafe_type_assertion(value as X) as Y as Z→ 2 findings (outer chain + inner chain)Rollback
A reverted commit restores current parenthesized detection behavior.