Schema.Class
一般的なclassのように、状態を持たせたオブジェクトを作るために使うのではないっぽいmrsekut.icon
GPT-4.icon
Schema.Class を使ってスキーマを定義することには、以下のような実用的なメリットがあります。
✅ 1. スキーマと型の同時定義(All-in-One)
Schema.Class を使えば、スキーマ定義と型定義を1箇所で済ませることができます。
通常、Schema.Struct を使うと type を別に定義する必要がありますが、Schema.Class はクラス自体がそのまま型になります。
code:ts
class Person extends Schema.Class<Person>("Person")({
id: Schema.Number,
name: Schema.NonEmptyString
}) {}
// Person はそのまま型として使える
const x: Person = new Person({ id: 1, name: "John" })
✅ 2. バリデーションつきのコンストラクタ
new Person({...}) でのインスタンス化時に、スキーマに従ったバリデーションが自動で行われます。
バリデーションエラーは詳細なエラーメッセージ付きで throw されるため、デバッグしやすい。
code:ts
new Person({ id: 1, name: "" })
// → throws: Predicate refinement failure: Expected NonEmptyString, actual ""
✅ 3. make ファクトリ関数の提供
Person.make({ ... }) という 便利な静的メソッドが使えるため、関数型スタイルのコードにも自然に組み込めます。
✅ 4. Equal や Hash による等価性の自動サポート
自動で Data.Class の Equal/Hash インターフェースを実装。
Equal.equals(a, b) でプロパティベースの等価比較が可能になります(deep equality も設定次第で対応可)。
✅ 5. Schema としての再利用性(スキーマでもある)
Schema.Array(Person) のように、スキーマとして他の構造に再利用できます。
decodeUnknownSync や encodeUnknownSync にも使える。
✅ 6. メソッドやゲッターでクラス拡張が可能
クラスなので、独自のロジックやプロパティ(ゲッター・メソッド)を簡単に追加できます。
code:ts
get upperName() {
return this.name.toUpperCase()
}
✅ 7. フィルタやバリデーションの追加が簡単
Schema.filter を通じて、構造以外の制約(例えば a > b など)も定義可能。
✅ 8. 型安全な再帰構造の定義が可能
Schema.suspend と組み合わせることで、再帰的な構造体も安全に表現できます(例: カテゴリツリーなど)。
✅ 9. 型注釈の補助(補完・明示化)
クラスとしての定義は TypeScript の補完にも強く、IDE 上での開発体験も良好です。
✅ 10. AST注釈によるメタ情報の付与
Schema.Class(..., [to, transform, from]) により、それぞれのスキーマに説明などの注釈をつけることができます。
extends
code:ts
import { Schema } from "effect"
// Define the base class
class Person extends Schema.Class<Person>("Person")({
id: Schema.Number,
name: Schema.NonEmptyString
}) {
// A custom getter that converts the name to uppercase
get upperName() {
return this.name.toUpperCase()
}
}
// Extend the base class to include an "age" field
class PersonWithAge extends Person.extend<PersonWithAge>("PersonWithAge")(
{
age: Schema.Number
}
) {
// A custom getter to check if the person is an adult
get isAdult() {
return this.age >= 18
}
}
// Usage
const john = new PersonWithAge({ id: 1, name: "John", age: 25 })
console.log(john.upperName) // Output: "JOHN"
console.log(john.isAdult) // Output: true