Skip to content

trimStart thowing on multi-character string chars is a breaking change and a Lodash compatibility break #1931

Open

Description

@foucdeg

Hello,

Just some feedback about the fix #1615 introduced in v1.49 (trimStart throwing an error when chars is a multi-character string).
While I understand and agree with the intention, transforming an undeterminate behaviour into a thrown error should have been considered a breaking change. It did break something on our side.
IMO, the better way to introduce this in a minor release should have been a deprecation warning.

I also suggest editing the docs to make this constraint more explicit. While the examples only show one-character strings, the spec for the argument does not specify that it should be a one-character string. This is especially important for people migrating from Lodash (as Lodash's equivalent does support multi-character strings - this breaks the 1-1 compatibility promise).

Thanks for the hard work!

Activity

  1. changed the title [-]trimStart thowing on multi-character string `chars` is a breaking change[/-] [+]`trimStart` thowing on multi-character string `chars` is a breaking change[/+] on Jul 21, 2026
  2. changed the title [-]`trimStart` thowing on multi-character string `chars` is a breaking change[/-] [+]`trimStart` thowing on multi-character string `chars` is a breaking change and a Lodash compatibility break[/+] on Jul 21, 2026
  3. Hprogram commented on Jul 22, 2026

    @Hprogram
    Contributor

    Some findings that might help triage this:

    The compat package is not affected — es-toolkit/compat's trimStart/trimEnd split a string chars into a character array before delegating (chars.toString().split('')), so they keep lodash's "set of characters" semantics and never throw. The existing compat tests cover multi-character strings (e.g. trimStart('-_-abc-_-', '_-')). So the 1-1 lodash compatibility promise still holds for es-toolkit/compat — the throw only affects the main es-toolkit package (introduced in #1615 for trimStart; trimEnd has the same validation, and trim inherits it from both).

    The docs were inconsistent about it — trimEnd's reference docs already document the constraint with an #### Errors section in all four languages, but trimStart and trim didn't mention it in any language.

    Whether the v1.49 behavior change should have been treated as breaking is of course a maintainer call — but regardless of that outcome, the docs should match the implementation, so I've submitted #1936 adding the missing Errors sections to trimStart/trim across the four languages, mirroring the existing trimEnd wording.

  4. foucdeg commented on Jul 22, 2026

    @foucdeg
    Author

    Thanks, I didn't know about es-toolkit/compat - makes more sense now.

  5. heeoneie commented on Aug 28, 2026

    @heeoneie

    A note on where this stands, since part of it moved after the report.

    The documentation half looks addressed already: #1936 landed on 2026-07-22 and added an Errors section to trim, trimStart, and trimEnd across all four languages — "Throws an error if chars is a string with a length other than 1." The source JSDoc carried the constraint before that.

    What still isn't written down anywhere is the second half of @foucdeg's report, the migration path. es-toolkit/compat's trim/trimStart/trimEnd run chars.toString().split('') before delegating, so they keep Lodash's "set of characters" semantics and never throw — the compat page even shows trimStart('-_-abc-_-', '_-'). But none of the twelve non-compat reference pages (trim/trimStart/trimEnd x en/ko/ja/zh_hans) mention compat at all. Someone arriving from Lodash hits the throw, reads "should be a single character", and has no reason to know the drop-in is one import away.

    I'd be glad to add that pointer — one line beside each Errors section, twelve files, no behavior change. Something like:

    Migrating from Lodash? es-toolkit/compat's trimStart accepts a multi-character chars and treats it as a set of characters, matching Lodash.

    On the release-policy part of the report — whether turning undefined behavior into a throw belonged in a minor, and whether a deprecation warning was the better path — that's a maintainer call and I won't presume it. If you'd rather settle that first and fold the docs line into whatever you decide, I'm happy to wait.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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