From a7ccd2b97e0088caee0fe26a72d78e608dd43acf Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Sat, 25 Apr 2026 04:33:54 +0200 Subject: [PATCH] fix(portal-types): clear residual long-tail tsc errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves the 4 tiptap-independent TypeScript errors that survived the tiptap 2.27.2 upgrade. All fixes are type-narrowing or type- annotation refinements; no runtime behavior changes. Errors fixed: - vite.config.ts:50 — TS7006: parameter 'componentName' implicitly has an 'any' type. Fix: annotate as `(componentName: string)`. The unplugin-vue-components resolver always passes a component-name string. - src/@layouts/types.ts:7 — TS2322 source: Type 'string' is not assignable to type 'Lowercase'. Vuexy boilerplate constrained `LayoutConfig.app.title` to all-lowercase, which rejects "Crewli Portal" in themeConfig.ts. The lowercase constraint serves no consumer in our code and was a Vuexy template oversight. Fix: relax type to `string` at the type definition (root cause). No call-site changes needed. - src/plugins/iconify/build-icons.ts:19 — TS2307: Cannot find module '@iconify/types' or its corresponding type declarations. The build:icons postinstall script uses `IconifyJSON` as a type annotation. `@iconify/types@2.0.0` was already in the pnpm store as a transitive dep of `@iconify/tools` but not hoisted to portal's node_modules root. Fix: add `@iconify/types` as an explicit dev-dependency. - src/@layouts/plugins/casl.ts:51 — TS2345: Argument of type '{}' is not assignable to parameter of type 'string'. Vue-router types `RouteMeta` loosely; the if-guard on line 50 narrows truthiness but TS doesn't infer string from `{}`. The same pattern on line 55 already uses `// @ts-expect-error`; we prefer an explicit `as string` cast at the call site since intent is clearer than a suppression comment. Fix: cast `targetRoute.meta.action` and `targetRoute.meta.subject` to `string` at the `ability.can(...)` call. vue-tsc errors: Pre: 4 own-code (post tiptap upgrade), 0 in node_modules. Post: 0 own-code, 0 in node_modules. apps/portal `pnpm exec vue-tsc --noEmit` now exits clean. Vitest: 113/113 passing. Build: 8.68s, succeeded. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/portal/package.json | 1 + apps/portal/pnpm-lock.yaml | 3 +++ apps/portal/src/@layouts/plugins/casl.ts | 2 +- apps/portal/src/@layouts/types.ts | 2 +- apps/portal/vite.config.ts | 2 +- 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/portal/package.json b/apps/portal/package.json index d0444b10..7cbd8406 100644 --- a/apps/portal/package.json +++ b/apps/portal/package.json @@ -77,6 +77,7 @@ "@iconify-json/mdi": "1.2.3", "@iconify-json/tabler": "1.2.23", "@iconify/tools": "4.1.4", + "@iconify/types": "^2.0.0", "@iconify/utils": "2.3.0", "@iconify/vue": "4.1.2", "@intlify/unplugin-vue-i18n": "11.0.1", diff --git a/apps/portal/pnpm-lock.yaml b/apps/portal/pnpm-lock.yaml index 52c65bd7..9f7397f9 100644 --- a/apps/portal/pnpm-lock.yaml +++ b/apps/portal/pnpm-lock.yaml @@ -190,6 +190,9 @@ importers: '@iconify/tools': specifier: 4.1.4 version: 4.1.4 + '@iconify/types': + specifier: ^2.0.0 + version: 2.0.0 '@iconify/utils': specifier: 2.3.0 version: 2.3.0 diff --git a/apps/portal/src/@layouts/plugins/casl.ts b/apps/portal/src/@layouts/plugins/casl.ts index c8fcd5c5..19c5dfa8 100644 --- a/apps/portal/src/@layouts/plugins/casl.ts +++ b/apps/portal/src/@layouts/plugins/casl.ts @@ -48,7 +48,7 @@ export const canNavigate = (to: RouteLocationNormalized) => { // If the target route has specific permissions, check those first if (targetRoute?.meta?.action && targetRoute?.meta?.subject) - return ability.can(targetRoute.meta.action, targetRoute.meta.subject) + return ability.can(targetRoute.meta.action as string, targetRoute.meta.subject as string) // If no specific permissions, fall back to checking if any parent route allows access // @ts-expect-error We should allow passing string | undefined to can because for admin ability we omit defining action & subject diff --git a/apps/portal/src/@layouts/types.ts b/apps/portal/src/@layouts/types.ts index 736fee08..ab1bb0ca 100644 --- a/apps/portal/src/@layouts/types.ts +++ b/apps/portal/src/@layouts/types.ts @@ -4,7 +4,7 @@ import type { AppContentLayoutNav, ContentWidth, FooterType, HorizontalNavType, export interface LayoutConfig { app: { - title: Lowercase + title: string logo: VNode contentWidth: typeof ContentWidth[keyof typeof ContentWidth] contentLayoutNav: typeof AppContentLayoutNav[keyof typeof AppContentLayoutNav] diff --git a/apps/portal/vite.config.ts b/apps/portal/vite.config.ts index 016de2fe..eea4b94c 100644 --- a/apps/portal/vite.config.ts +++ b/apps/portal/vite.config.ts @@ -47,7 +47,7 @@ export default defineConfig({ dirs: ['src/@core/components', 'src/components'], dts: true, resolvers: [ - componentName => { + (componentName: string) => { // Auto import `VueApexCharts` if (componentName === 'VueApexCharts') return { name: 'default', from: 'vue3-apexcharts', as: 'VueApexCharts' }