spatie/laravel-typescript-transformerを使ってみた
Dataクラスに限らずPHPのクラスも変換できる
PHPのクラスをTypeScriptに変換したい需要が謎だけど使ってみた
インストール
$ composer require spatie/laravel-typescript-transformer
設定を入れる
$ php artisan vendor:publish --tag=typescript-transformer-config
config/typescript-transformer.phpが追加される
$ composer require spatie/enum
変換方法
1. TypeScriptに変換したいクラスに/** @typescript */アノテーションか#[TypeScript]アトリビュートを付ける
2. typescript:transformコマンドを実行する
$ php artisan typescript:transform
オプションで色々指定
--pathオプションで変換対象のディレクトリとかファイル名を指定
--outputで出力先を指定
config/typescript-transformer.phpでも指定可能
code:options
Description:
Map PHP structures to TypeScript
Usage:
Options:
--force Force the operation to run when in production
--path=PATH Specify a path with classes to transform --output=OUTPUT Use another file to output --format Use Prettier to format the output
-h, --help Display help for the given command. When no command is given display help for the list command
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
--env=ENV The environment the command should run under -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
変換を試してみる
元のDataクラス
code:FooData.php
namespace App\Data;
use Carbon\CarbonImmutable;
use Spatie\LaravelData\Data;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;
use Spatie\TypeScriptTransformer\Attributes\TypeScriptType;
class FooData extends Data
{
public function __construct(
// Scalar types
public string $stringProp,
// Union types
public string|int $stringOrIntProp,
// nullable
public ?string $nullableStringProp,
// DataTime類はconfigのdefault_type_replacementsで指定されているのでstringになる
public CarbonImmutable $dateTime,
// stringのBacked Enum
public Lang $lang,
// 型を指定しない配列
public array $noneDocArray,
/** @var string[] */
public array $stringArray,
/** @var list<string> */
public array $stringList,
/** @var list<string|int> */
public array $stringOrIntList,
/** @var array<string, float> */
public array $keyStringValueFloatArray,
/** @var array{test: string} */
public array $objectLikeArray,
/** @var array{test?: string} */
public array $objectLikeWithOptionalArray,
'test' => '?string',
])]
public array $objectLikeArrayWithTypeScriptType,
) {
}
}
テスト用のBacked Enum
code:Lang.php
enum Lang: string
{
case JA_JP = 'ja_JP';
case EN_US = 'en_US';
}
変換後
code:resources/types/generated.d.ts
declare namespace App.Data {
export type Lang = 'ja_JP' | 'en_US';
export type FooData = {
stringProp: string;
stringOrIntProp: string | number;
nullableStringProp: string | null;
dateTime: string;
lang: App.Data.Lang;
noneDocArray: Array<any>;
stringArray: Array<string>;
objectLikeArray: Array<any>;
objectLikeWithOptionalArray: Array<any>;
objectLikeArrayWithTypeScriptType: {test:string | null;};
};
}
インデントとかはされない
別途ESLintとかPrettierでフォーマットする設定はある
変換を試したけどダメそうだったパターン
オブジェクトっぽい配列
変換するとArray<any>になってしまう
この場合はDataオブジェクトを入れ子にするか#[TypeScriptType]を使うと変換できる
ドキュメントを読むと色々なアトリビュートがある
arrayをRecordにするRecordTypeScriptTypeとか
所感
Backed EnumをTypeScriptのunion型に変換できるのは便利かも
PHPDocを書けばanyを回避して配列扱えるのも便利
けどT[]とlist<T>の解釈が逆
PHPでのstring[]がTypeScriptではArray<string>に,PHPでのlist<string>がTypeScriptでは{ [key: number]: string }として出力される
RecordTypeScriptTypeを使ってRecord型を生成したり,LiteralTypeScriptTypeを使ってリテラルを直接書いたりもできるけど,そこまでやるならPHPじゃなくて良くね感がある