Skip to content

Decide on the strict tsconfig flags wxt 0.21 introduced (currently opted out) #688

Description

@lmorchard

Background

wxt 0.21's generated .wxt/tsconfig.json turns on four compiler options that 0.20.27 did not:

  • verbatimModuleSyntax
  • noUncheckedIndexedAccess
  • noImplicitOverride
  • noFallthroughCasesInSwitch

Because packages/extension/tsconfig.json extends the generated config and maps pilo-core/core and pilo-core/ariaTree to core's sources via paths, the extension typecheck applies these to packages/core/src/** as well as the extension's own code. The wxt 0.21 bump (#687) therefore surfaced 64 errors in files it didn't touch.

In #687 I kept verbatimModuleSyntax on — it's the check that catches the value-import-of-a-type pattern that now hard-fails the rolldown/vite 8 release build ([MISSING_EXPORT] "Logger" is not exported by "../core/src/core.ts") — and fixed the 19 imports it flagged. The other three flags are explicitly disabled in packages/extension/tsconfig.json as a holding position, since adopting them meant 45 more changes inside a dependency bump.

What this issue is (and isn't)

I went through all 45. These are not latent bugs. Almost every one is a provably-safe access that the flag can't narrow:

  • packages/core/src/webAgent.ts:979this.messages[i] inside for (let i = this.messages.length - 1; i >= 0; i--)
  • packages/core/src/webAgent.ts:1369aiResponse.toolResults[0] guarded by if (aiResponse.toolResults.length > 1)
  • packages/core/src/browser/ariaTree/roleUtils.ts:480-489tokens[index] inside while (index < tokens.length)
  • packages/extension/src/background/ExtensionBrowser.ts:990-993return tabs[0] guarded by if (!tabs.length || !tabs[0].id) throw
  • 21 of the 45 are container.querySelector(...) / mock.calls[n] destructuring in test files

The two with any teeth are still low-impact:

  • ExtensionBrowser.ts ×5 — const [{ result }] = await browser.scripting.executeScript(...) throws TypeError: Cannot destructure property 'result' of 'undefined' if the array comes back empty (target frame gone). All five sites are already inside try/catch, so the observable difference is a confusing TypeError in the log instead of a clean error.
  • ExtensionBrowser.ts:246dataUrl.split(",")[1] passed to Buffer.from; only reachable if captureVisibleTab returns something that isn't a data URL.

packages/core/src/events.ts:547 (noImplicitOverride, TS4114) is the one genuinely correct finding: emit does override EventEmitter.emit and should say so. It's a one-word fix.

So this is a code-hygiene / config-coherence issue, not a correctness one. Filing it so the opt-out doesn't silently become permanent by accident.

Options

  1. Adopt the flags monorepo-wide — turn them on in core, cli, server and extension in one deliberate PR and fix the 45 sites. Coherent, and the flags then actually hold. Cost: a wide mechanical diff, mostly ! and ?. in tests.
  2. Adopt them for the extension only — smaller, but core would then be checked at two different strictness levels depending on which package compiles it, and core's own tsconfig.json wouldn't enforce it, so it would rot straight back.
  3. Keep the opt-out permanently and replace the comment in packages/extension/tsconfig.json with a link to this issue explaining the decision.

My read: (1) if the team wants the strictness, (3) if it doesn't. (2) is the worst of both. There's no urgency either way — nothing here is broken today.

packages/core/src/events.ts:547 is worth doing regardless of which option wins.

Full list

45 errors attributable to the three disabled flags
../core/src/browser/ariaTree/cssTokenizer.ts(101,5)  TS2322: Type 'number | undefined' is not assignable to type 'number'.
../core/src/browser/ariaTree/roleUtils.ts(480,26)  TS2532: Object is possibly 'undefined'.
../core/src/browser/ariaTree/roleUtils.ts(485,9)  TS2532: Object is possibly 'undefined'.
../core/src/browser/ariaTree/roleUtils.ts(489,26)  TS2532: Object is possibly 'undefined'.
../core/src/browser/ariaTree/roleUtils.ts(677,34)  TS2345: Argument of type 'HTMLOptionElement | undefined' is not assignable to parameter of type 'Element'.
../core/src/events.ts(547,3)  TS4114: This member must have an 'override' modifier because it overrides a member in the base class 'EventEmitter<string | symbol, any>'.
../core/src/snapshotCompressor.ts(167,7)  TS2322: Type 'string | undefined' is not assignable to type 'string'.
../core/src/webAgent.ts(1369,24)  TS2532: Object is possibly 'undefined'.
../core/src/webAgent.ts(1384,26)  TS18048: 'toolResult' is possibly 'undefined'.
../core/src/webAgent.ts(1936,24)  TS18048: 'firstToolResult' is possibly 'undefined'.
../core/src/webAgent.ts(979,11)  TS18048: 'msg' is possibly 'undefined'.
../core/src/webAgent.ts(979,48)  TS18048: 'msg' is possibly 'undefined'.
../core/src/webAgent.ts(980,9)  TS2322: Type '{ content: any[]; } | { content: any[]; role: "system"; providerOptions?: SharedV4ProviderOptions | undefined; } | { content: any[]; role: "user"; providerOptions?: SharedV4ProviderOptions | undefined; } | { ...; } | { ...; }' is not assignable to type 'ModelMessage'.
../core/src/webAgent.ts(982,21)  TS18048: 'msg' is possibly 'undefined'.
e2e/fixtures/extension.ts(72,15)  TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
src/background/ExtensionBrowser.ts(127,16)  TS2339: Property 'result' does not exist on type 'InjectionResult | undefined'.
src/background/ExtensionBrowser.ts(169,16)  TS2339: Property 'result' does not exist on type 'InjectionResult | undefined'.
src/background/ExtensionBrowser.ts(246,26)  TS2769: No overload matches this call.
src/background/ExtensionBrowser.ts(589,16)  TS2339: Property 'result' does not exist on type 'InjectionResult | undefined'.
src/background/ExtensionBrowser.ts(690,16)  TS2339: Property 'result' does not exist on type 'InjectionResult | undefined'.
src/background/ExtensionBrowser.ts(951,18)  TS2339: Property 'result' does not exist on type 'InjectionResult | undefined'.
src/background/ExtensionBrowser.ts(990,26)  TS2532: Object is possibly 'undefined'.
src/background/ExtensionBrowser.ts(993,5)  TS2322: Type 'Tab | undefined' is not assignable to type 'Tab'.
src/ui/components/sidepanel/SidePanel.tsx(93,23)  TS2345: Argument of type 'Tab | undefined' is not assignable to parameter of type 'SetStateAction<Tab | null>'.
test/background/configSeed.test.ts(136,20)  TS2532: Object is possibly 'undefined'.
test/background/configSeed.test.ts(240,29)  TS2532: Object is possibly 'undefined'.
test/background/configSeed.test.ts(260,20)  TS2532: Object is possibly 'undefined'.
test/background/configSeed.test.ts(273,20)  TS2532: Object is possibly 'undefined'.
test/background/indicatorControl.test.ts(147,45)  TS18048: 'lastCall' is possibly 'undefined'.
test/background/indicatorControl.test.ts(79,23)  TS18048: 'call' is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(1013,33)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(1052,22)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(1053,23)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(13,10)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(462,9)  TS18048: 'orphanEl' is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(700,35)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(729,35)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(756,35)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(786,35)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(815,35)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(844,35)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(913,33)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(937,33)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(967,33)  TS2532: Object is possibly 'undefined'.
test/components/sidepanel/ChatView.test.tsx(990,33)  TS2532: Object is possibly 'undefined'.

Reproduce by removing the three false overrides from packages/extension/tsconfig.json and running pnpm --filter pilo-extension run typecheck.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions