-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
String split return type #49635
Comments
|
Yeah, that 👆 |
@RyanCavanaugh @Josh-Cena I do think there is actually a bug here, if not the one OP is pointing to. Shouldn't the return type be Here is the behavior I'm getting: const test1 = 'test'; // type: 'test'
const splitresult1 = test1.split(':'); // type: string[]
const firstelement1 = splitresult1[0]; // type: string
const secondelement1 = splitresult1[1]; // type: string
console.log(test1) // test
console.log(splitresult1) // [ 'test' ]
console.log(firstelement1) // test
console.log(secondelement1) // undefined
const splitresult2 = "".split(""); // type: string[]
const firstelement2 = splitresult2[0]; // type: string
const secondelement2 = splitresult2[1]; // type: string
console.log(splitresult2) // []
console.log(firstelement2) // undefined
console.log(secondelement2) // undefined |
@AlecVision If you want that behavior please turn on |
Fixes microsoft#49635 Behavior similar to microsoft#49682 microsoft#49635 was originally rejected because JavaScript has a stupid edge case where `''.split('')` and `''.split(new RegExp(''))` return an empty array so we cannot assert that the first element is *always* a string. However, given that the vast majority of use cases for `split` include a literal separator, we can create a set of overloads that results in the non-empty literal separator returning a more narrow type that has a string for the first element. ```ts ''.split('') // []; type= string[] ''.split(new RegExp('')) // []; type= string[] ''.split('a') // ['']; type= [string, ...string[]] ''.split(new RegExp('a')) // ['']; type= string[] ``` Unfortunately, I don't know of a way to differentiate a regular expression literal and a regular expression so that case still always returns an empty first element even though I don't even think it is possible to have an empty regular expression literal. I don't *believe* there are any other edge cases where split can return an empty array, but if there are please let me know and I can try to update, or we can close the PR and just leave a comment on microsoft#49635 for the next person.
I'm not sure if the team monitors closed issues or if I should open a new issue, but I believe this JS edge case can be handled with: split(separator: '', limit?: number): string[];
split(separator: string, limit?: number): [string, ...string[]];
split(separator: string | RegExp, limit?: number): string[]; // test cases
const a = ''.split('') // []; type= string[]
const b = ''.split(new RegExp('')) // []; type= string[]
const c = ''.split('a') // ['']; type= [string, ...string[]]
const d = ''.split(new RegExp('a')) // ['']; type= string[] It makes it so if a non-empty string literal is provided then the first element is a string, otherwise it behaves as it does today. I don't believe there are any other edge cases where split can return an empty array. I don't know of a way to differentiate a regular expression literal and a |
It can return an empty array if you set the limit to interface String {
split<Separator extends string | RegExp, Limit extends number>(separator: Separator, limit?: Limit): Limit extends 0
? []
: Separator extends ''
? string[]
: [string, ...string[]]
} |
@MicahZoltu Consider the following: function doIt(str: string, sep: string) {
str.split(sep)[0].toUpperCase();
} This compiles with your overload, but An empty regex literal is "".split(/?:/);
"".split(/a?/); So I don't think this can be helped with in a generic way; you just have to assert for each individual use case. Alternatively, if we have negated types, you may be able to do |
Ah, you are totally right, I don't know why I thought this would work. 😬 |
lib Update Request
Configuration Check
My compilation target is
ES2020
and my lib isES2020
.Missing / Incorrect Definition
Method
split
of String currently has this signatureThis method, when called with a
limit
argument = 0, returns an empty array, but, when called withoutlimit
argument or with a non 0limit
argument, returns an array with at least one element (the initial string).This means the signature could be changed to acknowledge at least the "missing limit argument" case, where we are sure the array contains at least one element
Sample Code
Current situation:
Expected:
I called split without "limit", so I'm sure to find at least 1 element in the returned array
Documentation Link
https://262.ecma-international.org/11.0/#sec-string.prototype.split
The text was updated successfully, but these errors were encountered: