gvergnaud / hotscript

A library of composable functions for the type-level! Transform your TypeScript types in any way you want using functions you already know.
3.51k stars 59 forks source link

feat(String): RegExp `S.Replace`, `S.Match` and `S.MatchAll` #89

Closed didavid61202 closed 1 year ago

didavid61202 commented 1 year ago

Updates

  1. Add type-level-regexp as dependency.
  2. Update S.Replace to also accept RegExp pattern (/<pattern>/) as from arg to replace substring matched by the given pattern. Replace value also support special replacemnet patterns.
  3. add S.Match to match a string against a RegExp (support i and g flags), returns a matched object with match array and index and groups properties.
  4. add S.MatchAll to match a string against a RegExp, return an array of match objects, each with a match array and index and groups properties.
  5. S.Replace, S.Match and S.MatchAll all returns RegExpSyntaxError error type with detail error message when the provided RegExp contain Syntax error (currently only show few types of error, WIP)

Note

I have kept the implementation of RegExp matching and replacing generic types in a separate package called type-level-regexp. This allows for faster iteration as it is still in the early stages, and more features and performance improvements are coming along the way.

Usage

// Strings.Match exmaple
type MatchResult = Call<
        S.Match<"/a(?<g1>[b-e$]{1,4})\\W\\s\\b\\k<g1>(\\d+)/">,
        "12ab$c- b$c56#"
      >;
// type of `MatchResult` is:
// ["ab$c- b$c56", "b$c", "56"] & {
//   index: 2;
//   groups: {
//     g1: "b$c";
//   };
// }

// Strings.Replace exmaple
type ReplaceResult = Call<
//     ^? type ReplaceResult = "The release day is 2.13, 2023"
        S.Replace<
          "/((?:\\w|\\s)+):\\s(?<year>\\d{4})/(?<month>\\d{1,2})/(?<day>\\d{1,2})/",
          "The $1 is $<month>.$<day>, $2"
        >,
        "release day: 2023/2/13"
      >;

// RegExp syntax error exmaple
type SyntaxErrTest = Call<
        S.Match<"foo(?g1>bar)baz">,
        "foobarbaz"
      >;
// type of `SyntaxErrTest` is:
// {
//    type: "RegExpSyntaxError";
//    message: "Invalid regular expression, invalid capture group name for capturing `bar`, possibly due to a missing opening
//    '<' and group name";
// } & SyntaxError

Related issues

Resolve #33

Tasks

gvergnaud commented 1 year ago

@didavid61202 I tried this with a couple of use cases and this is great. I could find any bug with the regexp features I've tried so far, amazing job!

Something that worries me a little is the fact that your package has a global declaration altering string methods. I don't want hotscript to mess with global declarations to avoid unexpected side effects of installing this lib in an existing project. Do you think you could extract the pure type-level code in a different package?

ecyrbe commented 1 year ago

Oh oh, merged by mistake.

didavid61202 commented 1 year ago

@didavid61202 I tried this with a couple of use cases and this is great. I could find any bug with the regexp features I've tried so far, amazing job!

Something that worries me a little is the fact that your package has a global declaration altering string methods. I don't want hotscript to mess with global declarations to avoid unexpected side effects of installing this lib in an existing project. Do you think you could extract the pure type-level code in a different package?

Thanks @gvergnaud 😊

Do let me know if you find any bugs πŸ‘

I think that we do not have a global declaration side effect. I have made a subpath export (type-level-regexp/regexp instead of type-level-regexp) specifically for types, and importing from this subpath should not import the file that contain the global declaration. During my testing, I have not observed any side effects so far. However, I may have missed something that I am not aware of.

gvergnaud commented 1 year ago

@ecyrbe I'm going to override the main branch to unmerge

gvergnaud commented 1 year ago

Done. @didavid61202 Do you mind re-opening a PR?

didavid61202 commented 1 year ago

Done. @didavid61202 Do you mind re-opening a PR?

Done, re-open at #94 🎊 by the way, @gvergnaud do I still need to extract the pure type-level code in a different package for avoiding global declaration side effect? or subpath export of current setup is ok?

Thanks