sindresorhus / type-fest

A collection of essential TypeScript types
Creative Commons Zero v1.0 Universal
14.36k stars 546 forks source link

SnakeCaseProperties doesn't handle PascalCase and UPPERCASE #223

Open zirkelc opened 3 years ago

zirkelc commented 3 years ago

I have a type with PascalCase and a few uppercase properties, e.g.

Identifiers: {
    MarketplaceASIN: {
    MarketplaceId: string;
    ASIN: string;
    },
}

SnakeCasedPropertiesDeep turns this into:

_identifiers: {
    _marketplace_a_s_i_n: {
        _marketplace_id: string;
        _a_s_i_n: string;
    };
};

It doesn't handle the cases where the property starts with an uppercase and where the property contains multiple uppercase letters in a row.

I could overcome the first issue by using CamelCasedPropertiesDeep first.

What I would expect is:

identifiers: {
    marketplace_asin: {
        marketplace_id: string;
        asin: string;
    };
};

During runtime I use lodash's https://lodash.com/docs/4.17.15#snakeCase method. Is there a way to use the same method for the type?

Upvote & Fund

Fund with Polar

threehams commented 3 years ago

This looks like it might be fairly simple to fix. I've hacked in a userland fix for screaming snake case with this:

type IsScreamingSnakeCase<TString extends string> = Split<TString, ""> extends (
  | UpperCaseCharacters
  | WordSeparators
  | StringDigit
)[]
  ? true
  : false

type SnakeCase = <TString extends string>(
  str: TString,
) => IsScreamingSnakeCase<TString> extends true
  ? SnakeCase<Lowercase<TString>>
  : SnakeCase<TString>;

I'll submit a PR when I have time, hopefully it's as simple as it seems. PascalCase detection could be similar, hopefully, just lowercase the first letter in cases of mixed-case.

edit:

Narrator: It wasn't as simple as it seemed.

voxpelli commented 3 years ago

Best solution would be the one described here I think: https://github.com/sindresorhus/type-fest/issues/224#issuecomment-925357006