Skip to content

An empty string is falsy - #511

Merged
ASDAlexander77 merged 2 commits into
mainfrom
fix-empty-string-truthy
Oct 5, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
fix-empty-string-truthy

Conversation

@ASDAlexander77

@ASDAlexander77 ASDAlexander77 commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Closes #509.

"" was true in every boolean test of a string: if, while, !, ?:, && and ||, for a plain, optional, nullable or any string, under every memory model. So e || "x" gave "" and e && "x" gave "x". The string → boolean cast had no case of its own and fell to the generic pointer → boolean one in CastLogicHelper, which only compares the pointer with null.

Change

  • castStringToBool reads the first character and returns true when it is not the terminator. For a null string it reads the terminator of a static "" (a select of the pointer), so the test makes no branch and works in any region.
  • An optional string with no value has an undefined payload, which is not a pointer. Its test selects null in that case before reading. Other optionals are unchanged.

Test

00string_empty_falsy.ts tests "" and a non-empty string in each of those forms. It also covers a module-level "" ? 1 : 2, a global "", and empty strings made at run time (concatenation, template). ?? still keeps "". On main the first assertion fails.

It is registered for compile and JIT and in TSLANG_CORPUS (rc and none). It passes on the plain JIT under the default model, rc and none, with and without --opt, and as an --emit=exe. Under -mm=own without the default library, a smaller program covering if/!/?:/while/optional/literal gives the right answers.

ctest -C Release: 3857 of 3864 passed in the full run. The 7 failures were this test (6 registrations plus its ownership-verifier shard): its first version called substring, which the runner's --no-default-lib does not have. With that removed, all 7 pass. gtest unittests are not built in this tree.

DefaultLib

Merge ASDAlexander77/TypeScriptCompilerDefaultLib#24 with this PR. DefaultLib's endsWith, startsWith and indexOf used if (!searchString) as a null check. With "" falsy, "abc".endsWith("") would return false and indexOf("") would return -1. That PR makes the guards == null, which behaves the same under either compiler, so it can merge first. No other DefaultLib code tests a string for truthiness. No embedded TypeScript in this repo does either.

Re-enabled tests

28boolcasts.ts (if ("")) and 29lazyreferences.ts ("" || ..., "" && ...) had these cases commented out as TODO (""" should be false for boolean"). They are switched back on. On main each fails its assertion; with this change all 12 of their registrations pass.

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits October 5, 2026 15:53
`""` was true in every boolean test of a string: `if`, `while`, `!`,
`?:`, `&&` and `||`, for a plain, optional, nullable or `any` string,
under every memory model (#509). The string -> boolean cast had no case
of its own and fell to the generic pointer -> boolean one, which only
compares with null.

castStringToBool reads the first character and is true when it is not
the terminator. A null string reads the terminator of a static "", so
the test needs no branch and is safe in any region. An optional string
selects null when it has no value before reading, as the value of an
undefined optional is no pointer at all.

00string_empty_falsy.ts: each of those forms with "" and with a
non-empty string, a module-level `"" ? 1 : 2`, and empty strings made
at run time (concatenation, template). On main the first assertion
fails.

Closes #509

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
28boolcasts.ts had `if ("") { boolDie() }` commented out ("TODO: finish
it"), and 29lazyreferences.ts had `"" || ...` and `"" && ...` commented
out with "\"\" should be false for boolean". Both are right now (#509);
on main each fails its assertion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 61d3092 into main Oct 5, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-empty-string-truthy branch October 5, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An empty string "" is truthy in if / while / ! / ?: conditions

1 participant