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.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support regex patterns in `Strings.Replace`

gvergnaud opened this issue Β· comments

Wouldn't it be nice if we could write things like Strings.Replace<'([A-Z]_?[a-z])|([a-z]_?[A-Z])', '&1-&2'>?

If somebody is up for a type challenge, here is a playground: Playground 😘

import {Pipe, S, T, Compose} from 'hotscript'

export type CamelCase<Str> = Pipe<
  Str,
  [
    S.Replace<"/([a-z])([A-Z])/g", "$1-$2">,
    S.Replace<"_", "-">,
    S.Split<"-">,
    T.Map<Compose<[S.Capitalize, S.Lowercase]>>,
    T.Join<"">,
    S.Uncapitalize
  ]
>;

type res1 = CamelCase<"ONE_two-three">;
//   ^?
type test1 = Expect<Equal<res1, "oneTwoThree">>;
type res2 = CamelCase<"one_TWO-three">;
//   ^?
type test2 = Expect<Equal<res2, "oneTwoThree">>;
type res3 = CamelCase<"one_two-THREE">;
//   ^?
type test3 = Expect<Equal<res3, "oneTwoThree">>;
type res4 = CamelCase<"ONE_TWO-THREE">;
//   ^?
type test4 = Expect<Equal<res4, "oneTwoThree">>;
type res5 = CamelCase<"alreadyInCamelCase">;
//   ^?
type test5 = Expect<Equal<res5, "alreadyInCamelCase">>;

F.Compose was moved, here's an updated Playground

import {Pipe, Compose, S, T} from 'hotscript'

export type CamelCase<Str> = Pipe<Str, [
  // try replacing this
  S.Replace<'([A-Z]_?[a-z])|([a-z]_?[A-Z])', '&1-&2'>,
  // with:
  // S.Replace<'_', '-'>,
  S.Split<'-'>,
  T.Map<Compose<[S.Capitalize, S.Lowercase]>>,
  T.Join<''>,
  S.Uncapitalize
]>


type res1 = CamelCase<'ONE_two-three'>;
//   ^?
type test1 = Expect<Equal<res1, 'oneTwoThree'>>;
type res2 = CamelCase<'one_TWO-three'>;
//   ^?
type test2 = Expect<Equal<res2, 'oneTwoThree'>>;
type res3 = CamelCase<'one_two-THREE'>;
//   ^?
type test3 = Expect<Equal<res3, 'oneTwoThree'>>;
type res4 = CamelCase<'ONE_TWO-THREE'>;
//   ^?
type test4 = Expect<Equal<res4, 'oneTwoThree'>>;
type res5 = CamelCase<"alreadyInCamelCase">
//   ^?
type test5 = Expect<Equal<res5, 'alreadyInCamelCase'>>;




export type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <
    T,
>() => T extends Y ? 1 : 2
    ? true
    : false;

export type Expect<T extends true> = T;

Hi @gvergnaud, @franssu
I've made a PR #89 to implement this feature, did not include the example in this issue in the source code as I'm not sure here to put it, but you can copy and past the updated version below to test it out:

export type CamelCase<Str> = Pipe<
  Str,
  [
    S.Replace<"/([a-z]+)_(?<second>\\w+)/i", "$1-$<second>">,
    S.Split<"-">,
    T.Map<Compose<[S.Capitalize, S.Lowercase]>>,
    T.Join<"">,
    S.Uncapitalize,
    S.Match<"/(?<g1>[a-z]+)/i">,
    O.Get<"groups.g1">
  ]
>;

type res1 = CamelCase<"ONE_two-three">;
//   ^?
type test1 = Expect<Equal<res1, "oneTwoThree">>;
type res2 = CamelCase<"one_TWO-three">;
//   ^?
type test2 = Expect<Equal<res2, "oneTwoThree">>;
type res3 = CamelCase<"one_two-THREE">;
//   ^?
type test3 = Expect<Equal<res3, "oneTwoThree">>;
type res4 = CamelCase<"ONE_TWO-THREE">;
//   ^?
type test4 = Expect<Equal<res4, "oneTwoThree">>;
type res5 = CamelCase<"alreadyInCamelCase">;
//   ^?
type test5 = Expect<Equal<res5, "alreadyincamelcase">>;

And feedbacks or inputs are very welcome, thanks 😊