mosya
mosya Business はこちら

mosya<TC> - KebabCase<T>を実装してみようの解説

この記事はmosya<TC>の問題の一つであるKebabCase型の解説になります。

問題

キャメルケースもしくはパスカルケースの文字列を、ケバブケースに置換する方を実装します。

FooBarBaz -> foo-bar-baz

例えば以下のコードを満たすように実装しましょう。

type FooBarBaz = KebabCase<"FooBarBaz">;
const foobarbaz: FooBarBaz =
  "foo-bar-baz";

type DoNothing =
  KebabCase<"do-nothing">;
const doNothing: DoNothing =
  "do-nothing";

解答例

type KebabCase<S> =
  S extends `${infer S1}${infer S2}`
    ? S2 extends Uncapitalize<S2>
      ? `${Uncapitalize<S1>}${KebabCase<S2>}`
      : `${Uncapitalize<S1>}-${KebabCase<S2>}`
    : S;

まず、Sをinferと文字列リテラルを使って、最初の文字S1とそれ以降の文字S2に分割します。

type KebabCase<S> = S extends `${infer S1}${infer S2}` ...

次に、S2が小文字になっているかどうかを判定します。

type KebabCase<S> = S extends `${infer S1}${infer S2}`
  ? S2 extends Uncapitalize<S2> ...

もし小文字になっている場合は、S1を小文字にして、S2を再帰的に処理します。
大文字の場合は、S1を小文字にして、S2の前に-をつけて、S2を再帰的に処理します。

type KebabCase<S> = S extends `${infer S1}${infer S2}`
  ? S2 extends Uncapitalize<S2>
    ? `${Uncapitalize<S1>}${KebabCase<S2>}`
    : `${Uncapitalize<S1>}-${KebabCase<S2>}` 
  ...

これ以上、SをS1S2に分割できない場合は、Sをそのまま返します。

type KebabCase<S> =
  S extends `${infer S1}${infer S2}`
    ? S2 extends Uncapitalize<S2>
      ? `${Uncapitalize<S1>}${KebabCase<S2>}`
      : `${Uncapitalize<S1>}-${KebabCase<S2>}`
    : S;

Authored by

筆者の写真

Godai@steelydylan

Webサービスを作るのが好きなWebエンジニア。子供が産まれたことをきっかけに独立し法人化。サービス開発が大好き。
好きな言語はTypeScript。

ReactやTypeScriptなどの周辺技術が学べる
オンライン学習サービスを作りました!

詳しくはこちら
mosya

mosyaはオンラインでHTML,CSS,JavaScriptを基本から学習できるサービスです。現役エンジニアが作成した豊富なカリキュラムに沿って学習を進めましょう。

© 2023 - mosya. All rights reserved.