TypeScript {name: string} & string という型が never にならない理由

以下のような型があるとします。

type T1 = {name: string} & string

T1 は never にはなりません。

一見すると、name というプロパティを持つオブジェクト、かつ、文字列という型はないように見えます。

しかし、TypeScriptはこれを never としない理由があります。

実は以下のコードはエラーになりません。

type T3 = {length: number}
const b: T3 = 'tami'

これは、string が内部的にはプロパティを持つからです。

String オブジェクトには、その長さを返す length などのプロパティがあります。

これらのプロパティへのアクセスが発生する際に、文字列(プリミティブ)は一時的にStringオブジェクトへ変換されます。

このことを考慮して、T1 は never とはしません。

ここまで言うと、{name: string} のプロパティが、String オブジェクトに存在するかどうかまでをチェックすれば良いのでは?という発想になりますが、パフォーマンスの関係でそこまでTypeScriptはチェックしないようです。

ただし、実際に値を当てはめるとエラーになってくれるので、特に困ることはありません。

type T1 = {name: string} & string
const a: T1 = 'hoge' // Type 'string' is not assignable to type '{ name: string; }'.