Repository navigation
Systematically reduce @typescript-eslint/no-unsafe-type-assertion violations #94739
Description
If you run npm run eslint-report from App you can see our repo's eslint violations. The vast majority of these violations come from @typescript-eslint/no-unsafe-type-assertion.
About half the violations are in test suites vs production files:
┌────────────┬───────┬────────────┐
│ │ Files │ Violations │
├────────────┼───────┼────────────┤
│ Test files │ 485 │ 3,380 │
├────────────┼───────┼────────────┤
│ Prod files │ 861 │ 2,212 │
├────────────┼───────┼────────────┤
│ Total │ 1,346 │ 5,592 │
└────────────┴───────┴────────────┘
The ease of fixing these violations varies. Some are extremely simple and others are complex. We fixed some of the worst offending test suites in these two PRs (1, 2) by beginning to use a PartialDeep helper method for creating mock objects, but this is only for test files – and many violations still remain. The job of this issue is to get these number of violations down 📉
Changing one type can have cascading effects on the rest of the codebase. Careful use of Type Narrowing will be needed, and business logic will have to be preserved.
However, we can get good bang-for-our-buck here. A small number of files account for a disproportionate % of violations:
┌─────────┬───────┬────────────┬────────────┬────────────┐
│ Scope │ Files │ % of files │ Violations │ % of total │
├─────────┼───────┼────────────┼────────────┼────────────┤
│ Top 5 │ 5 │ 0.4% │ 547 │ 10% │
├─────────┼───────┼────────────┼────────────┼────────────┤
│ Top 10 │ 10 │ 0.7% │ 872 │ 16% │
├─────────┼───────┼────────────┼────────────┼────────────┤
│ Top 20 │ 20 │ 1.5% │ 1,344 │ 24% │
├─────────┼───────┼────────────┼────────────┼────────────┤
│ Top 50 │ 50 │ 3.7% │ 2,040 │ 36% │
├─────────┼───────┼────────────┼────────────┼────────────┤
│ Top 107 │ 107 │ 8% │ 2,803 │ 50% │
├─────────┼───────┼────────────┼────────────┼────────────┤
│ Top 372 │ 372 │ 28% │ 4,194 │ 75% │
└─────────┴───────┴────────────┴────────────┴────────────┘
So a full 3rd of these violations can be fixed by only touching 3.7% of the files with violations, and 75% of the violations can be fixed by only fixing 28% of the files. Good Pareto Principle example. Because of the nature of this issue, we've structured the payout in a unique way: you'll be paid by getting the total number of @typescript-eslint/no-unsafe-type-assertion to go down. This structure assumes (and incentivizes) the contributors working on it will knock out the easiest violations first, and the reward per violation goes up ⬆️ as you progress. Of course, removing the violations will also likely get harder as the low-hanging fruit all gets knocked out 😢.
┌───────────┬──────────────────────┬────────┐
│ Milestone │ Violations remaining │ Payout │
├───────────┼──────────────────────┼────────┤
│ Start │ 5,592 │ — │
├───────────┼──────────────────────┼────────┤
│ 1 │ ≤ 4,500 │ $250 │
├───────────┼──────────────────────┼────────┤
│ 2 │ ≤ 3,800 │ $250 │
├───────────┼──────────────────────┼────────┤
│ 3 │ ≤ 3,200 │ $250 │
├───────────┼──────────────────────┼────────┤
│ 4 │ ≤ 2,700 │ $250 │
├───────────┼──────────────────────┼────────┤
│ 5 │ ≤ 2,300 │ $250 │
├───────────┼──────────────────────┼────────┤
│ 6 │ ≤ 1,950 │ $250 │
├───────────┼──────────────────────┼────────┤
│ 7 │ ≤ 1,650 │ $250 │
├───────────┼──────────────────────┼────────┤
│ 8 │ ≤ 1,398 (75%) │ $250 │
├───────────┼──────────────────────┼────────┤
│ Total │ │ $2,000 │
└───────────┴──────────────────────┴────────┘
Guidelines:
- To minimize merge conflicts (and ease review load) PRs should be kept small. Ideally no more than 200 changed lines per PR. This will also make it easier to revert in case of regressions.
- Violation count will be calculated by checking
npm run eslint-reporton the latest version ofmain. - Once a count has been reached the contributor can notify the author of this issue (@blimpich) and I'll create a payout issue for the specific milestone you've reached. This way you're paid as you accomplish work rather than all at the end.
Activity
blimpich commentedon Jun 29, 2026
@KJ21-ENG and I talked in DM about them working on this issue. They are going to take over and start chipping away at it 👍
KJ21-ENG commentedon Jun 29, 2026
@blimpich Heyy 👋🏻
KJ21-ENG commentedon Jul 2, 2026
@blimpich I will start working on this today and will keep you updated on progress. Thanks!
blimpich commentedon Jul 2, 2026
Lovely thank you @KJ21-ENG!
blimpich commentedon Jul 2, 2026
As a heads up I'll be OOO tomorrow, but will be back Monday 👍
KJ21-ENG commentedon Jul 2, 2026
NP! I will try to get some work ready for review by the time you're back. 😄
333 remaining items
blimpich commentedon Oct 19, 2026
I'm open to increasing the payout but this will not be paid out at $250 or $175 a PR. Reducing eslint violations are not high-priority enough and part of the point of grouping this work all together is to get an economy of scale. If we wanted to get this done as quick as possible with a per-PR price tag we could've just made a bunch of individual issues and had contributors tackle it all in parallel. Having a team of people dedicated to it is slower but there is an efficiency gain where the people working it get better and faster at fixing individual eslint violations than if we just threw a crowd at it.
I want to respect your time as well, you don't have to work on this if you don't want to, but I'm being honest when I say I'm personally not willing to raise the price on this that much. If it's gotten too hard to reduce the number of violations then that might be a marker the marginal utility of this work has hit an inflection point.
@KJ21-ENG @ikevin127 if we increased the price of the final two milestones 2x (so $500 per milestone) would that be enough to justify your work on it? If not, then I think we should consider shutting this down.
ikevin127 commentedon Oct 19, 2026
Thanks @blimpich, fair points, and I appreciate you being upfront 🙌
Since you asked whether 2x would justify the work, here's the math from the author/reviewer side:
Where we are
~1,871 violations on
main. The latest 11 PRs currently open remove ~116, which brings us to ~1,755. That's still 105 short of milestone 7 and 357 short of milestone 8. Those PRs average ~10 violations each, so milestone 8 would take roughly 34 more PRs on top of them. Counting the 14 I reviewed over the past few days, that's ~48 reviews, nearly all touching production logic and needing manual testing + video proof.What 2x works out to
$1,000 across ~48 reviews is about $21 per review, roughly 12% of the current $175 rate for a manually tested authorship/review.
On economy of scale, I agree it's real on the implementation side, since @KJ21-ENG has clearly gotten faster at these. On the author/reviewer side it mostly isn't: every production PR still needs its own manual test and recorded video, and that takes the same time on the 40th PR as on the 1st.
What would work for me
$1,000 each for milestones 7 and 8 ($2,000 remaining). That's ~$42 per review, still a ~75% discount on the standard rate.
Note: @KJ21-ENG should confirm if this would work for them as well.
If that's more than this work is worth to you, I understand completely. In that case I'd suggest we wind down once the currently open PRs merge, with milestone 7 paid out at that point at your proposed $500 each, even though we'd land ~105 short of the 1,650 target, since that's where the review work has already gone.
Note
What'd be left is concentrated in large logic-heavy files (
ReportActionsUtils.ts,SearchUIUtils.ts,SearchQueryUtils.ts), which is probably the inflection point you mentioned.KJ21-ENG commentedon Oct 20, 2026
Thanks @blimpich and @ikevin127 for discussing this. From my side, I’m interested in continuing and completing the remaining work. I’m happy to leave the payment discussion to the two of you, and whatever arrangement you agree on for the remaining milestones will work for me.
blimpich commentedon Oct 20, 2026
@ikevin127 I don't think it's worth $1000 per milestone personally. $500 per milestone I think is what this is worth to Expensify as a company right now. @ikevin127 do you want to do milestone 7 at the new $500 price point and then leave the last milestone to a different C+ or would you rather stop now and leave both final milestones to be taken over by a different C+ (if any are interested)?
ikevin127 commentedon Oct 20, 2026
@blimpich Understood, thanks for laying out the options. I'll take milestone 7 at $500 and leave milestone 8 for another C+ after that.
@KJ21-ENG once the currently open / already reviewed PRs merge we'll be ~105 short of 1,650. Let's aim the next batch at files with the most violations so we close the gap to milestone 7 in as few PRs as possible 🙌
melvin-bot commentedon Oct 21, 2026
@ikevin127
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.15-3 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue: