Skip to content

[Regression] ${configDir} in extended tsconfig.json causes false type-safety errors #859

@alejandrohdezma

Description

@alejandrohdezma

When a tsconfig.json extends a base config that uses ${configDir} (the TypeScript 5.5 path variable) in outDir, include, or exclude, XO reports spurious errors like:

  • Unsafe assignment of an error typed value
  • Unsafe call of a type that could not be resolved

Replacing ${configDir} with ../ in the base tsconfig.json makes the errors go away, which indicates XO fails to resolve ${configDir} properly.

Reproduction

https://github.com/alejandrohdezma/xo-repro

The repo has the following setup:

tsconfig.json — extends a base config:

{
  "extends": "./remote_lib/tsconfig.json"
}

remote_lib/tsconfig.json — base config using ${configDir}:

{
  "compilerOptions": {
    "outDir": "${configDir}/dist",
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "strict": true
  },
  "include": ["${configDir}/src/**/*.ts"],
  "exclude": ["${configDir}/node_modules", "${configDir}/dist", "${configDir}/tests"]
}

src/config.ts — simple file using zod:

import {z} from 'zod'

export const Config = z.object({
  something: z.array(z.string()),
  other: z.object({
    something: z.string(),
  }),
})

export type Config = z.infer<typeof Config>

Steps:

  1. npm install
  2. npm run build (passes correctly)
  3. npm run check (produces false errors)
  4. Replace ${configDir} with ../ in remote_lib/tsconfig.json
  5. npm run check (no errors)

Context

I believe this is a regression — XO 0.60.0 apparently handled this correctly. ${configDir} is important for shared/company-wide base tsconfig.json files distributed as packages, where relative paths like ../ don't work reliably since the consuming project's directory depth is unknown. Without ${configDir}, every consuming project would need to override outDir, include, and exclude.

Workaround

Currently I'm solving this by pinning XO version to 0.60.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions