Skip to content

Improve string split return type of first array index #53362

Open

Description

@zardoy

lib Update Request

Please, consider improving user experience for "".split(...) in cases when string literal is passed, which I believe most users do e.g. split(' ') or split('\n')

Configuration Check

My compilation target is ES2015 and my lib is the default.

Missing / Incorrect Definition

split(separator: string | RegExp, limit?: number): string[];

Essentially duplicate of #49635, but with #49635 (comment) handled:

split<T extends string | RegExp>(separator: T, limit?: number): T extends `${string}${infer U}` ? [string, ...string[]] : string[];

And this should added to param JSDoc then: Only passing `""` and `new RegExp("")` values can result in returning an empty array.

Sample Code

This is super inconvenient when used with destructure:

const [firstLine, ...restLine] = str.split('\n')
// firstLine is possibly undefined, need add exclamation marks everywhere or `as [string, ...string]` above

I also wanted to do the same for when regexp literal is passed e.g. split(/\n\r?/) as only split(new RegExp('')) can result in empty array (if I'm not mistaken), which I believe no one does, but the literal value can't be captured anyway

Documentation Link

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#description (note)

P.S. I remembered of this issue after #49682, which significantly improved type-checking experience by using less exclamation marks

Activity

  1. RyanCavanaugh commented on Mar 21, 2023

    @RyanCavanaugh
    Member

    FWIW: we have a pretty low appetite for making the standard library definitions extremely complex for the sake of NUIA, which is a flag we added with significant hesitation because it makes things like these difficult to handle.

  2. EzioMercer commented on Jun 5, 2025

    @EzioMercer

    Original

    I came up with more strict overloads when limit is 0 and when separator is string:

    type Split<Source extends string, Separator extends string> = Source extends `${infer Left}${Separator}${infer Right}`
        ? [...(string extends Left ? string[] : [`${Left}`]), ...Split<Right, Separator>]
        : Source extends ""
          ? Separator extends ""
              ? []
              : [""]
          : string extends Source
            ? string[]
            : [Source];
    
    interface String {
        split<Source extends string, Separator extends string>(
            this: Source,
            separator: Separator,
            limit?: undefined,
        ): Split<Source, Separator>;
    
        split(separator: string | RegExp, limit: 0): [];
    }

    You can see types in action on playground (with examples)

  3. zardoy commented on Jun 5, 2025

    @zardoy
    ContributorAuthor

    Good that we have any activity there, Rovshan Badirkhanov (@EzioMercer) can you open your version of pr?;)

    The issue is still really annoying and I wish it could be fixed:(

  4. EzioMercer commented on Jun 6, 2025

    @EzioMercer

    Vitaly (@zardoy) I will try. Why did you dislike my issue?)

  5. kebi-gizachew commented on Aug 28, 2026

    @kebi-gizachew

    Hi Vitaly (@zardoy) , Rovshan Badirkhanov (@EzioMercer) , I’d like to work on this issue.
    I plan to explore refining the String.prototype.split overloads in lib.es5.d.ts so that destructuring the first element infers string instead of string | undefined when a non-empty separator is used.
    I’ll validate the changes with test cases to confirm improved inference and ensure compatibility with existing behavior.
    Please let me know if this approach aligns with what the team expects.

  6. zardoy commented on Aug 28, 2026

    @zardoy
    ContributorAuthor

    Hi Vitaly (@zardoy) , Rovshan Badirkhanov (@EzioMercer) , I’d like to work on this issue.
    I plan to explore refining the String.prototype.split overloads in lib.es5.d.ts so that destructuring the first element infers string instead of string | undefined when a non-empty separator is used.
    I’ll validate the changes with test cases to confirm improved inference and ensure compatibility with existing behavior.
    Please let me know if this approach aligns with what the team expects.

    Reported

  7. kebi-gizachew commented on Aug 28, 2026

    @kebi-gizachew

    Thanks for confirming. I’ll start working on a PR for this and will share updates once I have test cases ready.

  8. thw0rted commented on Aug 28, 2026

    @thw0rted

    LOL the bot thinks "Reported" means "sure thing buddy" 😂

  9. thw0rted commented on Aug 28, 2026

    @thw0rted

    For painful clarity: this suggestion has not been accepted by the TS maintainers and it sounds like they would prefer to avoid doing this. IMHO, noUncheckedIndexedAccess is Technically Correct (The Best Kind Of Correct), and this suggestion falls into the same bucket, so I'd love to see it implemented, but that's not the position of the maintainers.

    Ryan Cavanaugh (@RyanCavanaugh) if there is a condition under which this suggestion would be accepted, it would be good to hear that explicitly. If there is no foreseeable case in which the team would want to proceed in this direction, maybe the issue should just be closed? (I'd be sad to see it go but I don't know who it helps to just leave it sitting open in a contested state.)

  10. kebi-gizachew commented on Aug 28, 2026

    @kebi-gizachew

    Thanks for clarifying, James Bromwell (@thw0rted) — I appreciate the context.

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

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions