Closed7

Notion公式ライブラリで取得したデータのプロパティがサジェストで全部出てこずにエラー出す問題の解決

ピン留めされたアイテム
泡沫京水泡沫京水

読み飛ばしてすぐに5個目のコメント見てください

src/client/notion.ts
import { Client } from "@notionhq/client";
const NotionClient = new Client({auth: process.env.NOTION_SECRET as string})
export default NotionClient
src/Component/NotionPage.tsx
import Notionclient from "@/client/notion";

export default function NotionPage(){
    Notionclient.databases.query({
        database_id: process.env.DATABASE_ID as string,
        "sorts":[
            {
                property: "~~",
                direction: "descending"
            }
        ]
    }).then((res)=> {
        for(let i in res.results){
            console.log(res.results[0])
        }
    })
    return (<p>TEST</p>)
}

このとき、res.results[0]のプロパティは、idobjectしか持っていない状態になっている。しかし、console.log(res.results[0])を実行すると、より多くのプロパティが出現する。つまり、実際に返ってくるデータとデータの型定義が矛盾していることがわかる。

ピン留めされたアイテム
泡沫京水泡沫京水

ライブラリの中身こんな感じにいじる

node_modules/@notionhq/client/build/src/api-endpoints.d.ts
・・・
export type QueryDatabaseResponse = {
    type: "page";
    page: EmptyObject;
    object: "list";
    next_cursor: string | null;
    has_more: boolean;
    results: Array<PageObjectResponse>;
}
・・・

何をしているかというと、resultsの定義である、Array<PageObjectResponse | PartialPageObjectResponse>| PartialPageObjectResponseを消去する
これをすると、プロパティがしっかり全部出てくる

泡沫京水泡沫京水

代替案、ご指摘等あれば遠慮なくこのスクラップに投稿してください!!

nikogolinikogoli

以下のように「PageObjectResponse には存在して PartialPageObjectResponse には存在しないプロパティ」があることを if を使ってチェックすることで、PageObjectResponse のプロパティにアクセスできるようになります。

export default function NotionPage(){
    Notionclient.databases.query({
        //...
    }).then((res)=> {
        res.results.forEach(result => {
            if ("properties" in result){
                // 以降は型が PageObjectResponse に限定される
                console.log(result.url)
            }
        })
    })
    return (<p>TEST</p>)
}

これはどのクエリでも同様で、blocks.children.list() でページの中身を取得した場合も以下のようにプロパティをチェックして PartialBlockObjectResponse の型を弾くことになります。

await notion.blocks.children.list({block_id: id}).then(res => {
  res.results.forEach(block => {
   if ("type" in block){ // type の存在をチェックしないと .type へのアクセスが型エラーになる
      if (block.type=="heading_1") { /*...*/ }
      else if (block.type=="paragraph") { /*...*/ }
    }
  })
})

Notion API の型は、他にも~~Response型のオブジェクトが~~Request型のオブジェクトとして使えないことがあるなど厄介な部分が多いので、真面目に動かすのは結構大変です。

泡沫京水泡沫京水

なるほど、取得したデータを条件分岐で中身を調べることによって型を確定させるのですね!
アドバイスありがとうございます!やってみます!!

泡沫京水泡沫京水

問題が解決したのでクローズしました。
nikogoliさんの投稿を参考に
皆さんもやってみてください

このスクラップは2023/04/29にクローズされました