fix(portal-types): clear residual long-tail tsc errors

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<string>'. 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) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 04:33:54 +02:00
parent f7bb8645c4
commit a7ccd2b97e
5 changed files with 7 additions and 3 deletions

View File

@@ -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",

View File

@@ -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

View File

@@ -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

View File

@@ -4,7 +4,7 @@ import type { AppContentLayoutNav, ContentWidth, FooterType, HorizontalNavType,
export interface LayoutConfig {
app: {
title: Lowercase<string>
title: string
logo: VNode
contentWidth: typeof ContentWidth[keyof typeof ContentWidth]
contentLayoutNav: typeof AppContentLayoutNav[keyof typeof AppContentLayoutNav]

View File

@@ -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' }