メインコンテンツまでスキップ

公称型クラス

TypeScriptでは、クラスに1つでも非パブリックなプロパティがあると、そのクラスだけ構造的部分型ではなく公称型(nominal typing)になります。

たとえば、UserIdクラスとGroupIdクラスで同名になってしまっているidプロパティをプライベートにするだけで、相互の代入が不可能になります。

ts
class UserId {
private readonly id: string;
 
constructor(id: string) {
this.id = id;
}
}
 
class GroupId {
private readonly id: string;
 
constructor(id: string) {
this.id = id;
}
}
 
const userId: UserId = new GroupId("...");
Type 'GroupId' is not assignable to type 'UserId'. Types have separate declarations of a private property 'id'.2322Type 'GroupId' is not assignable to type 'UserId'. Types have separate declarations of a private property 'id'.
ts
class UserId {
private readonly id: string;
 
constructor(id: string) {
this.id = id;
}
}
 
class GroupId {
private readonly id: string;
 
constructor(id: string) {
this.id = id;
}
}
 
const userId: UserId = new GroupId("...");
Type 'GroupId' is not assignable to type 'UserId'. Types have separate declarations of a private property 'id'.2322Type 'GroupId' is not assignable to type 'UserId'. Types have separate declarations of a private property 'id'.

この方法はフィールドに限らず、プライベートメソッドやprotectedプロパティでも同じ効果があります。

関連情報

📄️ 構造的部分型

オブジェクト指向。そこまでとはいかなくてもクラスを扱うことができる言語において、ある元となる型(基本型 subtype)という話は欠かすことができません。