はじめに
このブログはNext.jsとTypeScriptで開発していますが、当方TypeScriptはまだまだ初学者で、
まだまだ作法や細かい仕様を理解しておらず、ぶつかっては覚えて、を繰り返しています。
今回もその躓きの一つで、メモっておきたいのでこの記事を書くことにします。
何をしていたか
Notion APIからのレスポンス用のtypeを用意しています。
Page情報からBlockの情報を見て、各ブロック用のentityに 情報を詰める処理 があります。
正しいブロックのtypeにキャストしてからentityに詰めるので、 結構厳格にtypeを作っている のですが、
共通して持つ情報も多いので、アンパサンドを用いて型をマージして表現しています。
例えばパラグラフ用のtypeだとこんな感じ。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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型の変数で赤波線が。
変数をホバーすると
1
type IParagraphBlock = never
うん?IParagraphBlockは_IBlock & { type: "paragraph", paragraph: _IParagraph }
型だが???
原因と解決策
おそらくこちらの記事の内容が原因。
TypeScript はちゃんと学習していないのですが、関わっているプロダクトが ts, tsx なので触る時に雰囲気で使っています。 今回はあるコンポーネントをラップするコンポーネントを作成していて、バックエンドから渡される値が、ラップするコンポーネントに定義されているPropsと異なっていて、ラップする側で足りない場合はデフォルト値を設定したいという感じでした。 👇こんなイメージ // ラップするコンポーネントの Props の型 type ModalProps = { modalMode: string; ... returnPath: string; }; // ラップするコンポーネン…
https://chaika.hatenablog.com/entry/2020/02/22/083000
typeの場合はinterfaceと違って同一プロパティのものは上書きされないのね。
今回の場合_IBlock.type
と_IParagraph.type
がコンフリクトを起こした結果、never型と判定されてしまったんだと思います。
今回は_IBlockは直接は使用されないので、_IBlock.type
を削除することで解決としました。