Repository navigation
Conversation
… does A property without a type annotation gets its type from its initializer. With noImplicitAny it can also get its type from the assignments in the constructor or a static block, or, when it's `declare`d, from the base class. tsc passes each of these types through `widenTypeForVariableLikeDeclaration`. bun did so only for the initializer, which caused several differences: - An object literal assigned in the constructor stayed fresh, so a later use checked its excess properties (a false TS2353). - TS7018 and TS7008 were missing without strictNullChecks. - A `unique symbol` that tsc widens to `symbol` was kept, so TS2322 and TS2416 were missing. One helper now widens all four. As in tsc, it keeps the `unique symbol` of an optional property under strictNullChecks, because by then the type is a union with `undefined`. That also fixes `x? = u`, which is wrong on main.
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Shared property widening and coverage src/sema/check/shape.rs, test/cli/check/differential-cases.json |
A shared helper widens inferred property types and conditionally reports implicit any. Initializer, constructor-flow, static-block-flow, and inherited property types use the helper. Differential cases cover constructor and static-block assignments, unique symbol inference, and optional properties. |
Possibly related PRs
- oven-sh/bun#46678: Both changes affect TypeScript type widening, though this PR addresses property declarations and that PR addresses synthesized object-literal types.
Suggested reviewers: jarred-sumner
Priority:
Merge Risk: 
Minimal · up to 9beac
-
No actionable issue is established; the change is mergeable after normal checks.
Pre-merge checks: 
4
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
What does this PR do?
A class property without a type annotation gets its type from its initializer. With
noImplicitAnyit can also get its type from the assignments in the constructor or a static block, or from the base class when it'sdeclared.tscpasses each of these types throughwidenTypeForVariableLikeDeclaration.bun checkdid that only for the initializer, which caused several differences:strictNullChecks.unique symbolthattscwidens tosymbolwas kept, so TS2322 and TS2416 were missing.One helper,
widen_type_of_property_declaration, now widens all four. As intsc, it keeps theunique symbolof an optional property understrictNullChecks, because by then the type is a union withundefined. That also fixesx? = u, which is wrong on main.How did you verify your code works?
test/cli/check/differential-cases.jsonmatchtsc7.0.2 byte for byte. Bun 1.4.4 differs on three of them. The fourth, withexactOptionalPropertyTypes, guards the optional case.bundle.zst, every test) stay at 100.00% byte for byte: 13,101 errors, 12,463 types, 12,463 symbols, 13,032 declarations and 151 traces. The 2,418 existing differential programs still matchtsc7.0.2.tsc7.0.2. They cover optional,readonly,#private,accessoranddeclareproperties, merges, cycles and checkJs. None got worse, and 181 that differed on main now match. The 24 that still differ also differ on main: cycles,SymbolConstructorand parenthesized assignment targets.bun check -breports andtscdoesn't.bun bd test. I ran these throughbun-semafromcargo build -p bun_sema_standalone, built from main at 179664e.bun check: TypeScript 7.1 #46383 as it is. There, the four programs matchtsc7.1 Beta, and 7.1's tests and differential programs still all pass.🤖 Generated with Claude Code