概要
部分型関係とは、2つの型の互換性を表す概念です。Animal型はHuman型を含んでいると言えます。Human型の田中さんはAnimal型でもあるということです。
そのため、以下のコードはTypescriptでコンパイルエラーになりません。
type Human = {
name: string,
age: number
}
type Animal = {
name: string
}
const tanaka: Human = {name: '田中', age: 35}
const tanaka2: Animal = tanaka
tanaka
という変数にHuman型の値を入れました。tanaka2
は age
を含まないAnimal型であるにも関わらずHuman型の値を入れることが可能です。これはHuman型はAnimal型の部分型であるからです。
しかし、だからと言ってtanaka2
は人間ではないため、ageプロパティにアクセスすることはコンパイルエラーが発生します。
console.log(tanaka2.age)
TS2339: Property 'age' does not exist on type 'Animal'.
部分型関係の成立条件
type Human = {
name: string,
age: number
}
type Animal = {
name: string
}
- Animal型に含まれているプロパティは全てHuman型に存在する。
これはAnimalにnameが含まれているのに対して、Humanにもnameというプロパティが存在するので満たしています
- 条件1で該当したプロパティの型が同じ
Animalのnameプロパティがstring型なのに対して、Human型も同様にstringなのでこの条件を満たしています。
よって、Human型はAnimal型の部分型であるということがわかります。
注意すべきこと
以下のコードは上のコードと似ていますが、Errorが発生します。
type Human = {
name: string,
age: number
}
type Animal = {
name: string
}
const tanaka: Human = {name: '田中', age: 35}
const tanaka2: Animal = {name: '田中', age: 35}
TS2322: Type '{ name: string; age: number; }' is not assignable to type 'Animal'. Object literal may only specify known properties, and 'age' does not exist in type 'Animal
先ほど説明した、部分型からの関係からすれば問題ないように見えるのですが型の安全性とは別にこのようなエラーが発生します。
tanaka2
は Animal型であるため、ageプロパティは存在しません。もちろん部分型の関係から代入は可能なのですが、どうせアクセスできないプロパティは無闇に書く必要はありません。だから上記のようなErrorが発生します。
このErrorはTypescriptによって出る場合とでない場合があります。下記のように
const tanaka2: Animal = {name: '田中', age: 35}
S2322: Type '{ name: string; age: number; }' is not assignable to type 'Animal'. Object literal may only specify known properties, and 'age' does not exist in type 'Animal'.
直接代入すると、ageプロパティは存在しないことが明らかであるためErrorが発生します
const tanaka: Human = {name: '田中', age: 35}
const tanaka2: Animal = tanaka
しかしこのように変数に一度おくとErrorは発生しなくなります。一旦変数に入れるとこのようなチェックは失われてしまうということです。