Repository navigation
String.split, low cost lib modification for narrowing return type of non-empty stringsΒ #56333
Copy link
Copy link
Closed as not planned
Closed as not planned
Copy link
Labels
DuplicateAn existing issue was already createdAn existing issue was already created
Description
π Search Terms
#52299 (closed)
#30406 (marked as design limitation)
β Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
β Suggestion
In es5.d.ts
before:
interface String {
split(separator: string | RegExp, limit?: number): string[];
}
after:
interface String {
split<S extends string>(separator: S): string extends S ? string[] :
S extends "" ? string[] : [string, ...string[]];
split(separator: string | RegExp, limit?: number): string[];
}
π Motivating Example
@noUncheckedIndexAccess: true
function checkField(fieldName: string){
let firstPathPart = fieldName;
if (fieldName.includes('.')) {
const partParts = fieldName.split('.');
firstPathPart = partParts[0]; // error
}
}
π» Use Cases
- What do you want to use this for?
As shown above
- What shortcomings exist with current approaches?
As shown above.
- What workarounds are you using in the meantime?
@noUncheckedIndexAccess: true
interface String {
split<S extends string>(separator: S): string extends S ? string[] :
S extends "" ? string[] : [string, ...string[]];
split(separator: string | RegExp, limit?: number): string[];
}
function checkField(fieldName: string){
let firstPathPart = fieldName;
if (fieldName.includes('.')) {
const partParts = fieldName.split('.');
firstPathPart = partParts[0]; // no error
}
}
{
// #53362 & #56332 & #56333 all give these results
const x1 = "".split('.'); // [string, ...string[]]
const x10 = x1[0]; // string
const x11 = x1[1]; // string | undefined
const x31 = "".split('.')[0]; // string
const x32 = "".split('.')[1]; // string | undefined
const x4 = "".split(''); // string[]
const x5 = "".split((0 as any as string)); // string[]
}
[playground](https://www.typescriptlang.org/play?#code/FDCWDsBcFMCcDMCGBjaACAypWEDmaBvYNEtAZwAcAbUSAHgzWgA8ZwATM87PAPgAoy0ColiJIAe1gAuTAEpZZHuHws2nTGgD83HCoDaAXTSzipc4zXQOXAES3tuvEZNp9SvbgA0aAHT+PZ0NDAG4zEkoaSEFhUXEpRWV8AB80ACVoXABRZgofGgBbWi1ZcABXAoAjOAUnA1DgAF8QeDLwZEhQCXA0ZAALaGQAawAxUGgqdn54ccmAOUQC6ETPOSJzKmhINBnYJQAFcT7D2G2AXh3Z9gWlsPNQeDRpq5voXwhkKjL2aDJ+AHJfP85HJCOFzL1uko0CJTidIFwLjMJtdFm9IrQAUC5HcISRdgcjvC0BdYZB4WR9AAGUJoAD0dLQ4AkTFgsCk4OazWAyCh22YAEYSWh7L4MdFAcCQvTGW5AiofP4xUkjIYeXy0MwAEzCwXU2kMuq4dXgaHMADMwtF4qxwP10sN8uNvNN-IALFbbGLqJj-lKZUajCazQBWT3eqL8fhUtCILiIcAAT1jXCdIIdjKdQaAA)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
DuplicateAn existing issue was already createdAn existing issue was already created
Activity
[-]String.split, lost cost improve for narrowing return type of non-empty strings[/-][+]String.split, low cost lib modification for narrowing return type of non-empty strings[/+]MartinJohns commentedon Nov 7, 2023
Duplicate of #53362.
fatcerberus commentedon Nov 7, 2023
How does this differ from #56332?
edit: nevermind, this was the "auxiliary proposal" from that one.
craigphicks commentedon Nov 7, 2023
Why it is not a duplicate of #53362
@MartinJohns
is not the same.
The type result is same. No problem with that - the result is good. 53362 wasn't declined just because it was useful.
The reason for declining 56333 was
The keyword is "extremely complex". Unfortunately it is not well defined. If that applies to this proposal we have learned something about what "extremely complex" means.
Why it is not a duplicate of #56332
@fatcerberus
This is the auxiliary proposal in 56332
The auxiliary proposal 56332 has a prerequisite that the element access part of proposal #34692 be implemented, and This proposal 56333 does not.
craigphicks commentedon Nov 8, 2023
@RyanCavanugh - This is not a duplicate. However, this could potentially declined for the same reason that #53362 was declined. In your reason for declining 53362 you used the expression extremely complex, which unfortunately is not well defined. It would helpful if you could clarify that meaning.
The evaluation extremely complex could mean using
infer. Or it could mean using any conditional expression. Or it could mean making any charge to a lib solely for the sake of NUIA.I'm inclined to believe that these would be good explicit rules:
noUncheckedIndexAccesscompiler option).RyanCavanaugh commentedon Nov 8, 2023
Complexity is relative to value provided. The value of
String#splitbeing a "provably non-empty" array is, in estimation, pretty low, in line with what you're saying.I'd say these are very good (especially re: NUIA), but not 100% rules (maybe 95%) ?
I don't really have a good place to write these down, but feel free to reference this comment (and I will likely do the same).
MartinJohns commentedon Nov 8, 2023
But it is. #53362 is about improving the type definitions for
String#split, and this issue is about improving the type definitions forString#split. The only difference is the approach suggested, but that does not really warrant a new issue, it can be added as a comment instead. Besides that, #53362 is not (yet) declined, it's awaiting more feedback.typescript-bot commentedon Nov 11, 2023
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.