This TypeScript warning occurs when using path mapping in tsconfig.json without enabling forceConsistentCasingInFileNames. While not a critical error, it can lead to cross-platform issues on case-insensitive file systems like Windows and macOS. Enable forceConsistentCasingInFileNames to ensure consistent file casing across all platforms.
This warning appears when your tsconfig.json contains a `paths` configuration for module path mapping, but the `forceConsistentCasingInFileNames` compiler option is not explicitly set to true. TypeScript issues this warning because path mapping can be particularly sensitive to file casing issues across different operating systems. The `forceConsistentCasingInFileNames` option ensures that when TypeScript resolves module imports, the casing of the import statement must match the actual file casing on disk. This is critical when using path aliases because: 1. **Windows and macOS** have case-insensitive file systems - `import "./Utils"` and `import "./utils"` both work 2. **Linux** has a case-sensitive file system - incorrect casing causes runtime errors 3. **Path mapping** (`paths` config) performs additional resolution that can amplify casing mismatches When you use path aliases like `@components/*` without this safeguard, code that works on Windows might break when deployed to a Linux production server. TypeScript recommends enabling this option whenever path mapping is used to catch these issues during development.
Open your tsconfig.json file and add or update the forceConsistentCasingInFileNames option in the compilerOptions section:
{
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"baseUrl": "./src",
"paths": {
"@components/*": ["components/*"],
"@utils/*": ["utils/*"],
"@lib/*": ["lib/*"]
}
}
}This setting ensures TypeScript checks that the casing in your import statements matches the actual file names on disk. The warning should disappear immediately after saving the file.
After enabling the option, TypeScript may reveal existing casing issues in your codebase. Run the compiler to check:
npx tsc --noEmitIf you see errors like "File name differs from already included file name only in casing", fix them by matching the import casing to the actual file:
// WRONG - file is actually "Button.tsx"
import { Button } from "@components/button";
// CORRECT - matches actual file casing
import { Button } from "@components/Button";
// WRONG - folder is actually "utils"
import { formatDate } from "@Utils/date";
// CORRECT
import { formatDate } from "@utils/date";Use your IDE's "Go to Definition" or file explorer to verify the actual casing of files and folders.
TypeScript language server may need a restart to recognize the configuration change:
VS Code:
1. Open Command Palette (Cmd/Ctrl + Shift + P)
2. Type "TypeScript: Restart TS Server"
3. Press Enter
WebStorm/IntelliJ:
1. File → Invalidate Caches → Restart
2. Or right-click tsconfig.json → TypeScript → Restart TypeScript Service
From terminal:
# Kill any running TypeScript processes
pkill -f "tsserver"
# Restart your development server
npm run devThis ensures your IDE picks up the new compiler setting and validates imports with the correct rules.
Ensure your paths configuration also has a proper baseUrl set. The two options work together:
{
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"baseUrl": "./src",
"paths": {
"@components/*": ["components/*"],
"@utils/*": ["utils/*"]
}
}
}With this configuration:
- baseUrl tells TypeScript where to start resolving paths
- paths defines the actual aliases
- forceConsistentCasingInFileNames ensures all imports match disk casing
Important: When using configuration inheritance (extends), set baseUrl with the correct casing:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./src", // Use absolute path or ensure correct casing
"forceConsistentCasingInFileNames": true
}
}Some developers report that using an absolute path for baseUrl resolves edge cases with path resolution.
Ensure your continuous integration validates casing across all platforms:
GitHub Actions example:
name: Type Check
on: [push, pull_request]
jobs:
typecheck:
runs-on: ubuntu-latest # Use Linux to catch casing issues
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npx tsc --noEmitGitLab CI example:
typecheck:
image: node:18
script:
- npm ci
- npx tsc --noEmitRunning type checks on Linux ensures that casing issues are caught before deployment, even if developers use Windows or macOS locally.
### Why Path Mapping Requires Consistent Casing
Path mapping creates virtual module resolution that can bypass normal file system checks. When TypeScript resolves an import like @components/Button:
1. It maps @components/* to src/components/* based on your paths config
2. It attempts to find the file at that location
3. On Windows/macOS, the file system returns the file even if casing is wrong
4. On Linux, incorrect casing fails at runtime (but TypeScript already compiled it)
The forceConsistentCasingInFileNames option makes TypeScript verify casing during step 2, catching the issue before deployment.
### Known Issues with Paths and Casing
There are several documented TypeScript issues related to this interaction:
Configuration inheritance problems:
When using extends in tsconfig.json, the baseUrl can get resolved with unexpected casing, particularly on case-insensitive file systems. This manifests as errors like:
File name 'C:/Project/src/...' differs from already included file name
'c:/Project/src/...' only in casingWorkaround: Set baseUrl explicitly in the extending configuration file, not just in the base config.
Node16/NodeNext module resolution:
When using moduleResolution: "node16" or "nodenext", type reference directives can break on macOS if there are capital letters in the project path. This is a known limitation tracked in TypeScript issue #50544.
### Best Practice tsconfig.json for Cross-Platform Projects
{
"compilerOptions": {
// Module resolution
"moduleResolution": "bundler", // or "node16" for Node.js
"baseUrl": "./src",
"paths": {
"@/*": ["./*"]
},
// Strict type checking
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
// Cross-platform compatibility
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"skipLibCheck": true,
// Output
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}### ESLint Rule for Import Casing
You can enforce correct casing at the linting level with eslint-plugin-import:
npm install -D eslint-plugin-import// .eslintrc.json
{
"plugins": ["import"],
"rules": {
"import/no-unresolved": "error"
},
"settings": {
"import/resolver": {
"typescript": {
"alwaysTryTypes": true
}
}
}
}This catches import casing issues even before TypeScript compilation.
### Debugging Casing Issues
If you're still experiencing casing-related errors after enabling the option:
1. Check actual file system casing:
# On Unix-like systems
find src -name "*.ts" -o -name "*.tsx"
# Look for duplicates that differ only in casing
find src -type f | sort -f | uniq -i -d2. Use TypeScript's trace resolution:
npx tsc --traceResolution > resolution.log
grep -i "casing" resolution.log3. Check Git configuration:
Sometimes Git on Windows checks out files with incorrect casing. Configure Git to preserve casing:
git config core.ignorecase false### Migration Strategy for Large Codebases
If you have an existing large codebase with many casing issues:
1. Enable the option but temporarily set it to false
2. Gradually fix files in batches
3. Use a script to find all casing mismatches:
// find-casing-issues.js
const { execSync } = require('child_process');
const output = execSync('npx tsc --noEmit 2>&1', { encoding: 'utf-8' });
const casingErrors = output.match(/differs.*only in casing/g);
console.log(`Found ${casingErrors?.length || 0} casing issues`);4. Once all issues are fixed, enable forceConsistentCasingInFileNames: true permanently
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript