2つの型の互換性を表す概念。
型Sが、型Tの部分型であるとき、型Sの値が型Tの値でもあることを表す。
type Bar = {
  name: string;
  gender: string;
  age: number;
}
type Foo = {
  name: string;
  gender: string;
}
const bar: Bar = {
  name: "kona",
  gender: "male",
  age: 23,
};
const foo: Foo = bar;
console.log(foo);上記の例では、Bar型は、Foo型の部分型であるといえる。なのでFoo型の変数fooに、Bar型の変数barを代入することができている。
BarはFooが持っていないageプロパティを持っているが、Fooではname,genderプロパティ以外には言及されていないため、余分なプロパティがあっても問題ない。
ただし、持っていないプロパティにアクセスするのはコンパイルエラーになる。
オブジェクトの場合、プロパティの包含関係によって部分型関係を説明できる。
型S, 型Tがオブジェクト型であるとし、以下の2つの条件が満たされていればSはTの部分型である。
const foo: Foo = {
  name: "kona",
  gender: "male",
  age: 23,
};
// 型 '{ name: string; gender: string; age: number; }' を型 'Foo' に割り当てることはできません。
// オブジェクト リテラルは既知のプロパティのみ指定できます。'age' は型 'Foo' に存在しません上記の例は、オブジェクトリテラルでFoo型の変数にBar型と同じ型を代入しているが、エラーになる。
オブジェクトリテラルでの代入は、TypeScriptが補助的にエラーを出力してくれる。(余分なプロパティはいらないので)
SがTの部分型なら、(arg: U) => Sという関数型は、(arg: U) => Tという関数型の部分型になる。
type HasName = {
  name: string;
};
type HasNameAndAge = {
  name: string;
  age: number;
};
const fromAge = (age: number): HasNameAndAge => ({
  name: "kona",
  age
});
const f: (age: number) => HasName = fromAge;
const obj: HasName = f(100);
console.log(obj); // { name: 'kona', age: 100 }上記の例では、HasNameAndAge型はHasName型の部分型である。
変数fは、 (引数: number) => HasName という関数型であり、これに (引数: number) => HasNameAndAge を代入している。
出力結果から、objはnameプロパティだけしかないオブジェクトにはならず、ageプロパティも所持している。
TypeScriptでは型情報によってランタイムの挙動に影響を与えない。
また、どんな型を返す関数型も、voidを返す関数型の部分型として扱われる。以下の書き方も可能。(余分な返り値は無視すれば良いので)
const v: (age: number) => void = fromAge;type HasName = {
  name: string;
};
type HasNameAndAge = {
  name: string;
  age: number;
};
const showName = (obj: HasName) => {
  console.log(obj.name);
};
const g: (obj: HasNameAndAge) => void = showName;
g({
  name: "kona",
  age: 23,
});上の例では、
HasNameという型を引数に持つshowName関数を、
HasNameAndAgeという型を引数に持つg関数へ代入している。
これはHasName型を受け取る関数の型が、HasNameAndAge型を受け取る関数の部分型であるといえる。
オブジェクトの部分型では、HasNameAndAge型が、HasName型の部分型であった。
引数の部分型関係は逆転する。
オブジェクトの場合は、HasName型に定義したプロパティ以外のプロパティがあっても関係ないので、HasNameAndAge型を代入することができる。
→ HasNameAndAge型はHasName型である。
関数の引数の場合、関数(HasName型を受け取る)のメソッドで使用するプロパティは、引数で定義されているプロパティなので、そのプロパティが定義されている引数の関数(HasNameAndAge型を受け取る)ならば、代入することができる。(余分なプロパティは無視すれば良いので)
→ HasName型を受け取る関数の型はHasNameAndAge型を受け取る関数の型でもある。
type Double = (arg: number) => number;
type Plus = (left: number, right: number) => number;
const d: Double = arg => arg * 2;
const p: Plus = (left, right) => left + right;
const bin: Plus = d;
console.log(bin(50, 1)); // 100上の例では、Plus型の関数にDouble型の関数を代入している。
DoubleはPlusの部分型。
Plusより引数が少ないため、余分なものは無視される。