tsでtypeを&で繋ぐとnever型になってしまった話

tsでtypeを&で繋ぐとnever型になってしまった話

はじめに

このブログはNext.jsとTypeScriptで開発していますが、当方TypeScriptはまだまだ初学者で、
まだまだ作法や細かい仕様を理解しておらず、ぶつかっては覚えて、を繰り返しています。

今回もその躓きの一つで、メモっておきたいのでこの記事を書くことにします。

何をしていたか

Notion APIからのレスポンス用のtypeを用意しています。
Page情報からBlockの情報を見て、各ブロック用のentityに情報を詰める処理があります。

正しいブロックのtypeにキャストしてからentityに詰めるので、結構厳格にtypeを作っているのですが、

共通して持つ情報も多いので、アンパサンドを用いて型をマージして表現しています。

例えばパラグラフ用のtypeだとこんな感じ。

type _IBlock = {
    type: 'block';
    object: 'block';
    id: string;
    created_time: string;
    last_edited_time: string;
    has_children: boolean;
    archived: boolean;
}

export type IText = {
	...
}
type _IParagraph = { text: IText[], children: IRetrieveBlockChildrenResponse }
export type IParagraphBlock = _IBlock & { type: "paragraph", paragraph: _IParagraph }

(名称にIが入っているのは、もともとinterfaceで作っていた名残です)

何がおきたか

vscodeでコーディングしていると、IParagraph型の変数で赤波線が。
変数をホバーすると

type IParagraphBlock = never

うん?IParagraphBlockは_IBlock & { type: "paragraph", paragraph: _IParagraph }型だが???

原因と解決策

おそらくこちらの記事の内容が原因。

typeの場合はinterfaceと違って同一プロパティのものは上書きされないのね。
今回の場合_IBlock.type_IParagraph.typeがコンフリクトを起こした結果、never型と判定されてしまったんだと思います。

今回は_IBlockは直接は使用されないので、_IBlock.typeを削除することで解決としました。