🤖
TypeScriptにおける値オブジェクトの表現
メールアドレスが以下のルールを持つとすると、ルールに当てはまらない場合に例外を発生させることができます。
- 値の型がStringである。
- 値の最後が@int.dayである。
それぞれのルールをコードにする
メールアドレスは以下のように表現できます。
const email = "xxx@int.day"
システムではこのメールアドレスを検査する必要があります。何故なら、変数にはどんな値が入っているのか分からないからです。
例えばメールアドレスは以下のようなルールを満たしています。
- 型がstringである。
- 値に@マークが含まれる。
これらのルールを満たさない時、例外を発生させることができます。
// 型確認
if ( !email.includes("@") ) {
throw new Error("エラー")
}
if (typeof email !== "string") {
throw new Error("エラー")
}
zodを使って短く表現する
parse関数にemailを渡している、もしこの値がemailじゃなければ例外が発生します。
import { z } from "zod"
const zValue = z.string().email()
zValue.parse(email)
Emailを値オブジェクトとして表現する
メールアドレスはclassで以下のように表現できます。
export class Email {
constructor(public value: string) {
}
}
メールアドレスのインスタンスを生成して使います。
emailの引数はconstructorの型を見ればわかります。const email = new Email("xxx@int.day")
email.value // xxx@int.day
しかし、メールアドレスの以外の文字列でもインスタンスを生成出来てしまいます。
そこで、constructorで例外を発生させます。
export class Email {
constructor(public value: z.infer<typeof zValue>) {
zValue.parse(value)
}
}
メールアドレスじゃない文字列でインスタンスを生成した場合、例外が発生します。
テストをする
この二つをテストします。
- インスタンスを作成する
- メールアドレスでないと例外が発生する
jestを使ったらこのようにテストできます。
import { Email } from "integrations/domain"
describe("Email", () => {
test("インスタンスを作成する", () => {
const email = new Email("xxx@int.day")
expect(email.value).toBe("xxx@int.day")
})
test("メールアドレスでないと例外が発生する", () => {
const email = () => new Email("foo")
expect(email).toThrowError()
})
}
Discussion