How to fix Condition will always be 'true' or 'false' in TypeScript
This TypeScript error indicates a logical condition that the type checker has determined will always evaluate to the same boolean value. This typically happens due to type narrowing, incompatible type comparisons, or redundant checks that make code unreachable.
Quick fix
Fixes Condition will always be 'true' or 'false'
let value: string | null = getValue();
if (value === null) {
console.log("null");
} else {
// Here, value is narrowed to 'string' (not null)
if (value === null) { // ERROR: Always false - value can't be null here
console.log("unreachable");
}
}- Understand type narrowing and review your conditional logic
- Remove the redundant condition
- Fix type comparisons with correct types
- Simplify boolean conditions
let value: string | null = getValue();if (value === null) {console.log("null");} else {// Here, value is narrowed to 'string' (not null)if (value === null) { // ERROR: Always false - value can't be null hereconsole.log("unreachable");}}Condition will always be 'true' or 'false'
What this error means
TypeScript's type narrowing engine analyzes your code to determine the most specific type possible at any given location. When the compiler detects a condition that will always be true or false based on type information, it reports this error. This usually means either: 1. You're checking a condition that's already been narrowed to a different type 2. You're comparing incompatible types (like checking if a number equals a boolean) 3. You've already narrowed a value in a way that makes the condition impossible This is actually a helpful warning—it catches redundant or logically impossible code that could indicate a bug.
Typical symptoms
- TypeScript shows 'Condition will always be true (or false)' error
- Code appears logically correct but the compiler rejects it
- The error occurs on if statements, while loops, or ternary operators
- Adding type assertions or unnecessary checks is suggested as a workaround
- The warning appears after strict null checks are enabled
Common causes
- Comparing a non-null type with null after it's been narrowed (most common)
- Checking a boolean variable against a literal boolean (e.g., if (isValid === true))
- Type narrowing from a previous condition makes the next check impossible
- Comparing incompatible types (e.g., number === string literal)
- Union type has been narrowed in a way that eliminates all possibilities except one
- Comparing a type with itself when it can only be one value
How to fix "Condition will always be 'true' or 'false'"
First, understand why TypeScript thinks the condition is always true/false. The error usually points to a logical inconsistency in your code.
Review the variable's type before the condition:
let value: string | null = getValue();
if (value === null) {
console.log("null");
} else {
// Here, value is narrowed to 'string' (not null)
if (value === null) { // ERROR: Always false - value can't be null here
console.log("unreachable");
}
}In this example, the second value === null check is always false because the else block already guarantees value is not null.
Delete or restructure the condition that will always be the same value.
Before:
function processString(str: string | null) {
if (str !== null) {
if (str === null) { // Always false - ERROR
console.log("Never reached");
}
}
}After:
function processString(str: string | null) {
if (str !== null) {
// str is now guaranteed to be a string
console.log(str.length); // No condition needed
}
}If you're comparing with a literal value, ensure the comparison makes logical sense.
Problem - comparing with wrong type:
const isActive: boolean = true;
if (isActive === "true") { // ERROR: boolean can't equal string "true"
console.log("always false");
}Solution - compare with correct type:
const isActive: boolean = true;
if (isActive === true) { // Correct, but usually just write: if (isActive)
console.log("active");
}Boolean comparisons to literal values are often redundant. Simplify them.
Before:
const isEnabled = checkFeature();
if (isEnabled === true) { // Redundant: always true when isEnabled is true
doSomething();
}After:
const isEnabled = checkFeature();
if (isEnabled) { // Cleaner and same logic
doSomething();
}If you have a union type, use explicit type guards to narrow safely.
Problem:
function processValue(value: string | number) {
if (typeof value === "string") {
// value is narrowed to 'string' here
if (typeof value === "number") { // ERROR: always false
console.log("unreachable");
}
}
}Solution - use proper type narrowing:
function processValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase()); // Can use string methods
} else {
console.log(value.toFixed(2)); // Can use number methods
}
}When strictNullChecks is enabled, null and undefined have distinct types. Verify your assumptions match.
Problem with strictNullChecks:
function getValue(): string {
return "hello";
}
const value = getValue(); // Type is 'string', never null/undefined
if (value === null) { // ERROR: Always false - string can't be null
console.log("unreachable");
}Solution - use proper optional types:
function getValue(): string | null {
return Math.random() > 0.5 ? "hello" : null;
}
const value = getValue(); // Type is 'string | null'
if (value === null) { // Now valid - value could be null
console.log("null case");
} else {
console.log(value.toUpperCase());
}Advanced notes
### Disabling the Check (Not Recommended)
If you absolutely need to keep the always-true/false condition (rare), you can suppress the error:
// @ts-expect-error This condition is always true, but we need it for compatibility
if (legacyCondition === true) {
console.log("This might seem redundant but is needed for legacy reasons");
}However, this should be very rare. Most of the time, the error indicates actual logic bugs.
### TypeScript Configuration
The error checking is controlled by TypeScript's type checking. To see all such errors, ensure your tsconfig.json has strict mode enabled:
{
"compilerOptions": {
"strict": true,
"strictNullChecks": true,
"noImplicitAny": true
}
}### Related Issues in Type System
Similar "always true/false" patterns can occur with:
- Literal type narrowing
- Discriminated unions (where one property determines possible values)
- Type predicates (custom type guards)
In all cases, the fix is to update your conditions to align with the type system's understanding.
### Debugging Type Narrowing
If you're unsure what TypeScript thinks a type is at a specific point, use the "reveal type" technique:
function debug<T>(x: T): T {
type Check = typeof x; // Hover over 'Check' to see the type
return x;
}This helps you understand why a condition seems "always true/false" from the compiler's perspective.
Frequently asked questions
- What does "Condition will always be 'true' or 'false'" mean?
- TypeScript's type narrowing engine analyzes your code to determine the most specific type possible at any given location. When the compiler detects a condition that will always be true or false based on type information, it reports this error. This usually means either: 1.
- How do I fix "Condition will always be 'true' or 'false'"?
- This TypeScript error indicates a logical condition that the type checker has determined will always evaluate to the same boolean value. This typically happens due to type narrowing, incompatible type comparisons, or redundant checks that make code unreachable.
- What causes "Condition will always be 'true' or 'false'"?
- Comparing a non-null type with null after it's been narrowed (most common) Checking a boolean variable against a literal boolean (e.g., if (isValid === true)) Type narrowing from a previous condition makes the next check impossible
- Is the "Condition will always be 'true' or 'false'" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖TypeScript Handbook - Type Narrowing(Official Docs)
- 📖TypeScript TSConfig - strictNullChecks(Official Docs)
- 📖TypeScript TSConfig - allowUnreachableCode(Official Docs)
- 🐙
- 🐙
- 🐙