Clean Architecture の文脈でEntityに書くときに使えそうなものをメモとして書いておく。
tl;dr
とりあえずはclass
使う。
class
を使う
class Id {
constructor(readonly value: number) {}
}
class MailAddress {
constructor(readonly value: string) {}
}
class User {
constructor(
readonly id: Id,
readonly mailAddress: MailAddress,
) {}
}
const u = new User(new Id(0), new MailAddress("hoge@fuga.foo"));
good
-
instanceof
が使えるので型の特定が楽 - 関数をもたせたりできるので柔軟性が高い
bad
- 特に感じていないが、強いて言えばJavaっぽい。
interface
を使う
const ID = "id";
type ID_TYPE = "id";
interface Id {
readonly type: ID_TYPE;
readonly value: number;
}
const MAIL_ADDRESS = "mail_address";
type MAIL_ADDRESS_TYPE = "mail_address";
interface MailAddress {
readonly type: MAIL_ADDRESS_TYPE;
readonly value: string;
}
const USER = "user";
type USER_TYPE = "user";
interface User {
readonly type: USER_TYPE;
readonly id: Id;
readonly mailAddress: MailAddress;
}
const _id: Id = { type: ID, value: 10 };
const _mailAddress: MailAddress = { type: MAIL_ADDRESS, value: "hoge@fuga.foo" };
const u: User = {type: USER, id: _id, mailAddress: _mailAddress};
good
- 生成後のjsがシンプル
-
Pick
とかが使える
bad?
-
typeof
とかを使うと単にプリミティブ型が出てきちゃうだけで、型の判定ができない。- あくまでトランスパイル時に型チェックが入るだけなので、実行時のでの判定ができない。
- => そのため、
type
という変数を入れている。
bad部分に関しては自信ないので他の方法があれば知りたい。
type
を使う
type Id = number;
type MailAddress = string;
type User = { id: Id, mailAddress: MailAddress};
const _id: Id = 20;
const _mailAddress: MailAddress = "hoge@fuga.foo";
const u: User = { id: _id, mailAddress: _mailAddress };
good
- シンプル
- valueとかいらない
bad?
- type aliasがあるだけなので、型が違くても入れられちゃうケースがある。
- もとが
string
だったら何でも入る、みたいな感じ
- もとが
bad部分に関しては自信ないので他の方法があれば知りたい。
まとめ
現時点ではclass
使って全部定義しちゃうでいいかも。
でもオーバーヘッド掛かりそうでそこ気にしちゃうな。
あと、TypeScript Playground超便利
ツッコミマサカリは絶賛募集中です。