This error occurs when TypeScript detects that two seemingly identical types are actually incompatible, often due to duplicate package versions, circular type references, or complex conditional type inference issues.
The "Type is not assignable to itself" error is one of TypeScript's most confusing messages because it appears to violate basic logic - how can a type not be compatible with itself? This error occurs when TypeScript's type system determines that what appears to be the same type is actually represented by two different, incompatible type instances. The most common cause is duplicate package installations where different versions of the same package create separate type definitions. For example, if you have two versions of @babel/types installed, TypeScript treats TSTypeAliasDeclaration from version 7.4.0 as incompatible with TSTypeAliasDeclaration from version 7.5.0, even though they have the same name. The error can also occur with complex type scenarios involving circular references, conditional types with infer, or branded/template literal types where TypeScript's type inference creates multiple representations of what should be the same type.
First, identify if you have duplicate versions of packages installed. This is the most common cause.
For npm:
npm ls <package-name>
# Example: npm ls @babel/typesFor yarn:
yarn why <package-name>
# Example: yarn why @babel/typesFor pnpm:
pnpm why <package-name>Look for multiple version numbers in the output. If you see different versions, proceed to the next steps.
If you're using Yarn, force all packages to use the same version by adding a resolutions field to your package.json:
{
"resolutions": {
"@babel/types": "^7.23.0",
"@types/node": "^20.0.0"
}
}Then reinstall dependencies:
rm -rf node_modules yarn.lock
yarn installReplace the version numbers with the latest compatible version for your project.
For npm version 8.3 or later, use the overrides field in package.json:
{
"overrides": {
"@babel/types": "^7.23.0",
"@types/node": "^20.0.0"
}
}Then clean install:
rm -rf node_modules package-lock.json
npm installCached packages can cause version conflicts. Clear your package manager's cache:
For npm:
npm cache clean --forceFor yarn:
yarn cache cleanFor pnpm:
pnpm store pruneAfter clearing the cache, reinstall all dependencies:
rm -rf node_modules
npm install # or yarn install / pnpm installIf the error involves circular type references, restructure your types to avoid self-referential inheritance:
Problematic:
// Don't do this - circular inheritance
interface A extends B {}
interface B extends A {}
// Or this - type alias referencing itself
type Tree = {
value: string;
children: Tree[]; // This can work as a property
}
type BadTree = Tree | BadTree[]; // But not in a unionFixed:
// Use properties instead of inheritance
interface Node {
next?: Node; // Property reference is OK
value: string;
}
// Or use an interface for recursive structures
interface TreeNode {
value: string;
children: TreeNode[]; // Interfaces handle recursion better
}If the error occurs with conditional types using infer, try simplifying the type logic:
Problematic:
type Extract<T> = T extends Foo<infer U> ? U : T;
function process<T>(value: T): Extract<T> {
// Type is not assignable to itself
return value;
}Fixed:
// Add explicit type annotations
function process<T>(value: T): Extract<T> {
return value as Extract<T>;
}
// Or restructure to avoid conditional in return type
function process<T extends Foo<any>>(value: T): T extends Foo<infer U> ? U : never {
// ...
}Alternatively, use a helper type with fewer constraints:
type Unwrap<T> = T extends Foo<infer U> ? U : never;
function process<T extends Foo<any>>(value: T): Unwrap<T> {
return value.inner;
}Monorepo Considerations: In monorepos using workspaces, this error often occurs when different packages depend on different versions of shared types. Use a root-level package.json with resolutions/overrides to enforce consistent versions across all workspace packages.
TypeScript Version Sensitivity: Some complex type scenarios that trigger this error in older TypeScript versions may be resolved in newer versions. If you're using branded types or template literal types, consider upgrading to TypeScript 5.0+ which has improved type inference.
Branded Types: When using branded types (nominal typing), ensure you're creating new branded values correctly. Mixing branded and unbranded values can trigger this error:
type UserId = string & { __brand: 'UserId' };
// Wrong - unbrandΠ΅d string
const id1: UserId = '123'; // Error
// Correct - properly branded
const id2 = '123' as UserId;Performance Impact: Deeply nested or highly complex conditional types can cause TypeScript to create multiple type representations during type checking, leading to this error. Simplifying your type definitions can improve both compilation performance and reliability.
pnpm Strict Mode: pnpm's strict dependency resolution can prevent many duplicate version issues that cause this error, but may require explicit configuration of peer dependencies in package.json.
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