Improve DelimiterCase#930
Conversation
|
@voxpelli Could you take a look? At the moment I just want to know if this is something I should dig deeper into |
|
@filipw01 Its not immediately obvious to me what the improvements are, and my experience with these helpers has been that they easily turn into a game of whackamole – any improvement reveals a couple of regressions. I do see that you ultimate refer to my wish to unify the two: #224 (comment)
But that was ultimately solved through a new option instead: #501 I guess my main feedback would be to split this PR into more commits and try to make it as clear what and why the changes made are made, so that one can as easily as possible follow the reasoning in a review |
|
For the no split on number I decided to align with |
source/split-words.d.ts
Outdated
| ? [...SkipEmptyWord<CurrentWord>, ...SplitWords<RemainingCharacters, FirstCharacter, FirstCharacter>] | ||
| // Case change: numeric to non-numeric, push word | ||
| // Split on number: push word | ||
| ? Options['splitOnNumber'] extends true |
There was a problem hiding this comment.
When there's a numeric/non-numeric case change I added and used a new option splitOnNumber which depending on how it is set will either
- When set to true - Like before split words on number
- When set to false - concat to current word
| @category Template literal | ||
| */ | ||
| export type ScreamingSnakeCase<Value> = Value extends string | ||
| ? IsScreamingSnakeCase<Value> extends true |
There was a problem hiding this comment.
I can bring this back, but I believe it shouldn't be necessary, especially that we don't use it for other things like snake case or kebab case
test-d/kebab-case.ts
Outdated
| const kebabFromMixed2: KebabCase<'parseHTML'> = 'parse-html'; | ||
| expectType<'parse-html'>(kebabFromMixed2); | ||
|
|
||
| const kebabFromMixed3: KebabCase<'parseHTMLItem'> = 'parse-html-item'; | ||
| expectType<'parse-html-item'>(kebabFromMixed3); | ||
|
|
||
| const kebabFromNumberInTheMiddleSplitOnNumber: KebabCase<'foo2bar'> = 'foo-2-bar'; | ||
| expectType<'foo-2-bar'>(kebabFromNumberInTheMiddleSplitOnNumber); | ||
|
|
||
| const kebabFromNumberInTheMiddleSplitOnNumberEdgeCase: KebabCase<'foO2Bar'> = 'fo-o-2-bar'; | ||
| expectType<'fo-o-2-bar'>(kebabFromNumberInTheMiddleSplitOnNumberEdgeCase); | ||
|
|
||
| const kebabFromNumberInTheMiddleSplitOnNumberEdgeCase2: KebabCase<'foO2bar'> = 'fo-o-2-bar'; | ||
| expectType<'fo-o-2-bar'>(kebabFromNumberInTheMiddleSplitOnNumberEdgeCase2); | ||
|
|
||
| const kebabFromNumberInTheMiddleNoSplitOnNumber: KebabCase<'foo2bar', {splitOnNumber: false}> = 'foo2bar'; | ||
| expectType<'foo2bar'>(kebabFromNumberInTheMiddleNoSplitOnNumber); | ||
|
|
||
| const kebabFromNumberInTheMiddleNoSplitOnNumberEdgeCase: KebabCase<'foo2Bar', {splitOnNumber: false}> = 'foo2-bar'; | ||
| expectType<'foo2-bar'>(kebabFromNumberInTheMiddleNoSplitOnNumberEdgeCase); | ||
|
|
||
| const kebabFromNumberInTheMiddleNoSplitOnNumberEdgeCase2: KebabCase<'foO2bar', {splitOnNumber: false}> = 'fo-o2bar'; | ||
| expectType<'fo-o2bar'>(kebabFromNumberInTheMiddleNoSplitOnNumberEdgeCase2); | ||
|
|
||
| const kebabFromNumberInTheMiddleNoSplitOnNumberEdgeCase3: KebabCase<'FOO22Bar', {splitOnNumber: false}> = 'foo22-bar'; | ||
| expectType<'foo22-bar'>(kebabFromNumberInTheMiddleNoSplitOnNumberEdgeCase3); |
There was a problem hiding this comment.
I added the same tests to all case types as well as some edge cases visible here. If you have any doubts about the implementation I can add more tests
source/kebab-case.d.ts
Outdated
| // Simple | ||
|
|
||
| const someVariable: KebabCase<'fooBar'> = 'foo-bar'; | ||
| const someVariableNoSplitOnNumber: KebabCase<'p2pNetwork', {splitOnNumber: false}> = 'p2p-network'; |
There was a problem hiding this comment.
I added this new option on case changing types
| : Parts extends [string] | ||
| ? string | ||
| : ''; | ||
| type DelimiterCaseFromArray< |
There was a problem hiding this comment.
This gets the words split and inserts the delimited at the beginning and after every word
Like ['here', 'We', 'Go'] -> '#here#We#Go'
source/delimiter-case.d.ts
Outdated
| Delimiter | ||
| > | ||
| */ | ||
| export type DelimiterCase<Value, Delimiter extends string, Options extends SplitWordsOptions = {splitOnNumber: true}> = Value extends string |
There was a problem hiding this comment.
Here we
'hereWeGo'-> SplitWords ->['here', 'We', 'Go']['here', 'We', 'Go']-> DelimiterCaseFromArray ->'#here#We#Go''#here#We#Go'-> RemoveFirstLetter ->'here#We#Go''here#We#Go'-> Lowercase ->'here#we#go'
|
@voxpelli At this point where all the commits are made I'd prefer not to do any git wizardry splitting into smaller commits. I left some comments for easier review. I hope this will be enough. If something is unclear let me know. I tried to add more edge cases to avoid the whack a mole game |
|
#975 is also touching some of these files. I will not have time to review either, just noting it |
|
@sindresorhus any chance to move this forward? |
source/delimiter-case.d.ts
Outdated
| Delimiter | ||
| > | ||
| */ | ||
| export type DelimiterCase<Value, Delimiter extends string, Options extends SplitWordsOptions = {splitOnNumber: true}> = Value extends string |
There was a problem hiding this comment.
SplitWordsOptions = {splitOnNumber: true} will not allow us to add more options in the future, as if you specify one, you override the existing defaults.
|
You need to resolve the merge conflict. |
|
And maybe |
e983b73 to
5bd9be0
Compare
|
Looks good 😉 |
| }; | ||
|
|
||
| type DefaultOptions = { | ||
| splitOnNumbers: true; |
There was a problem hiding this comment.
Should this default to false? 4.36.0 seems to be a breaking change since I have to set this to false to avoid errors using KebabCase.
I made some changes that pass more test cases than the current solution. I was heavily inspired by
CamelCaseimplementationOpinions seem to be mixed from one library to another how

hello123case should be handledEven more interestingly, those libraries that default to
hello_123don't have an option to customize it, but those that default tohello123have optional parameters to change thatI made the type customizable via a parameter to fit both cases
Related issues:
#223
#336
What I'd still like to add: