Skip to content

Add TypeScript foundation and upgrade build tooling - #3794

Open
Vondry wants to merge 1 commit into
bolt:6.2from
Vondry:chore/typescript-foundation
Open

Add TypeScript foundation and upgrade build tooling#3794
Vondry wants to merge 1 commit into
bolt:6.2from
Vondry:chore/typescript-foundation

Conversation

@Vondry

@Vondry Vondry commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Add TypeScript foundation and upgrade build tooling

Second step of the Vue 3 / TypeScript migration, which adds TypeScript to the existing Vue 2.7 codebase without touching component logic

Changes

  • Encore 1.8.2 → 4.7.0 — the last release supporting Vue 2 (5.0 dropped it). Brings sass-loader 14 and postcss-loader 8, and drops vue-template-compiler.
  • TypeScripttsconfig.json (strict, .ts-only include), ts-loader via enableTypeScriptLoader(), npm run typecheck + a CI step, and typescript-eslint scoped to assets/**/*.ts.
  • Filters converted to TS, and Vue 2 global filters (Vue.filter() / $options.filters, both removed in Vue 3) replaced with direct imports at all 13 call sites.

Review notes

  • enableVueLoader()'s version option is deliberately omitted. It only accepts 2 or 3, and 2 selects the target that still requires vue-template-compiler. Unset, Encore detects vue@2.7 and uses the SFC compiler Vue 2.7 ships itself.
  • SFCs are not type-checked yet — none use lang="ts". That comes when they move to <script setup lang="ts"> and the checker becomes vue-tsc.

Behaviour

Unchanged, except trim(), strip() and uppercase() no longer throw a TypeError on null/non-string input. Values that previously rendered are unaffected — trim() still passes non-strings through untouched rather than coercing, so numbers aren't truncated and objects don't become [object Object].

Verified by diffing the compiled render functions of all changed SFCs, and by a 348-case differential harness against the pre-migration implementations.

Next

Vitest + tests for the converted filters, then components to Composition API.

Testing

I manually clicked through the admin pages and verified that they work as previously

image

First step of the staged Vue 3 / TypeScript migration. Introduces
TypeScript on the existing Vue 2.7 codebase without touching any
component logic, so the eventual framework swap lands as a much
smaller, mechanical change.

Build tooling:

- Upgrade @symfony/webpack-encore 1.8.2 -> 4.7.0. 4.7 is the last
  release supporting Vue 2; Encore 5.0 dropped it. The version option
  of enableVueLoader() is deliberately omitted: it only accepts 2 or 3,
  and passing 2 selects the target that still requires
  vue-template-compiler. Left unset, Encore detects vue@2.7 and picks
  its "vue2.7" target, which uses the SFC compiler Vue 2.7 ships
  itself, so vue-template-compiler is no longer needed.
- Bump sass-loader 9 -> 14 and postcss-loader 4 -> 8 to match Encore
  4.7's peer ranges, and add webpack and webpack-cli as explicit
  dependencies as Encore 4 requires.
- Drop @babel/plugin-transform-regenerator and
  @babel/plugin-transform-runtime, which were declared but unreferenced.

TypeScript:

- Add tsconfig.json with strict plus noImplicitReturns,
  noFallthroughCasesInSwitch, noImplicitOverride, isolatedModules,
  allowUnreachableCode false and allowUnusedLabels false. The include
  list is .ts/.d.ts only; the SFCs have no lang="ts" yet, so they are
  not type-checked until they move to <script setup lang="ts"> and the
  checker becomes vue-tsc.
- Add typescript 6, ts-loader and @types/luxon, wire ts-loader through
  Encore.enableTypeScriptLoader(), and add a typecheck script plus a CI
  step running it.
- Scope typescript-eslint to assets/**/*.ts so the Vue 2 SFCs keep
  being linted by the vue2 preset.

Filters:

- Convert assets/js/filters and assets/js/services/api to TypeScript.
- Replace the Vue 2 global filters, removed in Vue 3, with directly
  imported functions at all 13 call sites across 7 components. Return
  types are inferred rather than annotated.

Behaviour is unchanged apart from trim(), strip() and uppercase() no
longer throwing a TypeError on null or non-string input. Values that
previously rendered are unaffected: trim() still passes non-strings
through untouched instead of coercing them, so numbers are not
truncated and objects do not become "[object Object]".
@Vondry

Vondry commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

I created follow up #3797 with test setup.

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.

1 participant