Documentation Index Fetch the complete documentation index at: https://mintlify.com/makenotion/notion-sdk-js/llms.txt
Use this file to discover all available pages before exploring further.
Notion API responses often include partial objects when the full object wasn’t requested or isn’t available. The SDK provides type guard functions to help you safely distinguish between full and partial responses.
Why Type Guards?
Many Notion endpoints return union types like PageObjectResponse | PartialPageObjectResponse. Type guards let you:
Check if a response contains full details
Safely access properties that only exist on full objects
Get proper TypeScript type narrowing
Available Type Guards
All type guards are exported from the main package:
import {
isFullPage ,
isFullBlock ,
isFullDataSource ,
isFullDatabase ,
isFullUser ,
isFullComment ,
isFullPageOrDataSource ,
} from "@notionhq/client/build/src/helpers"
Page Type Guards
isFullPage
Checks if a response is a full PageObjectResponse.
function isFullPage (
response : ObjectResponse
) : response is PageObjectResponse
Implementation: Returns true if response.object === "page" and has a url property.
Example:
const response = await notion . pages . retrieve ({ page_id: "page-id" })
if ( isFullPage ( response )) {
// TypeScript knows this is PageObjectResponse
console . log ( response . url )
console . log ( response . properties )
console . log ( response . created_time )
} else {
// This is PartialPageObjectResponse
console . log ( "Only have basic page info" )
}
Block Type Guards
isFullBlock
Checks if a response is a full BlockObjectResponse.
function isFullBlock (
response : ObjectResponse
) : response is BlockObjectResponse
Implementation: Returns true if response.object === "block" and has a type property.
Example:
const blocks = await notion . blocks . children . list ({ block_id: "block-id" })
for ( const block of blocks . results ) {
if ( isFullBlock ( block )) {
console . log ( block . type ) // "paragraph", "heading_1", etc.
console . log ( block . created_time )
console . log ( block . has_children )
}
}
Data Source Type Guards
isFullDataSource
Checks if a response is a full DataSourceObjectResponse.
function isFullDataSource (
response : ObjectResponse
) : response is DataSourceObjectResponse
Implementation: Returns true if response.object === "data_source".
Example:
const response = await notion . dataSources . retrieve ({
data_source_id: "data-source-id" ,
})
if ( isFullDataSource ( response )) {
console . log ( response . id )
console . log ( response . created_time )
}
isFullPageOrDataSource
Checks if a response is either a full PageObjectResponse or DataSourceObjectResponse. Useful when working with search or query results.
function isFullPageOrDataSource (
response : ObjectResponse
) : response is DataSourceObjectResponse | PageObjectResponse
Implementation: Checks for full data source first, otherwise checks for full page.
Example:
const searchResults = await notion . search ({
query: "meeting notes" ,
})
for ( const result of searchResults . results ) {
if ( isFullPageOrDataSource ( result )) {
console . log ( result . id )
if ( result . object === "page" ) {
console . log ( "Page URL:" , result . url )
} else {
console . log ( "Data source ID:" , result . id )
}
}
}
Database Type Guards
isFullDatabase
Checks if a response is a full DatabaseObjectResponse.
function isFullDatabase (
response : ObjectResponse
) : response is DatabaseObjectResponse
Implementation: Returns true if response.object === "database".
Example:
const response = await notion . databases . retrieve ({
database_id: "database-id" ,
})
if ( isFullDatabase ( response )) {
console . log ( response . title )
console . log ( response . properties )
}
User Type Guards
isFullUser
Checks if a response is a full UserObjectResponse.
function isFullUser (
response : UserObjectResponse | PartialUserObjectResponse
) : response is UserObjectResponse
Implementation: Returns true if the response has a type property.
Example:
const users = await notion . users . list ({})
for ( const user of users . results ) {
if ( isFullUser ( user )) {
console . log ( user . type ) // "person" or "bot"
console . log ( user . name )
if ( user . type === "person" ) {
console . log ( user . person . email )
}
}
}
Checks if a response is a full CommentObjectResponse.
function isFullComment (
response : CommentObjectResponse | PartialCommentObjectResponse
) : response is CommentObjectResponse
Implementation: Returns true if the response has a created_by property.
Example:
const comments = await notion . comments . list ({
block_id: "block-id" ,
})
for ( const comment of comments . results ) {
if ( isFullComment ( comment )) {
console . log ( comment . created_by )
console . log ( comment . created_time )
console . log ( comment . rich_text )
}
}
Rich Text Type Guards
For rich text items, use these type guards to determine the content type:
isTextRichTextItemResponse
function isTextRichTextItemResponse (
richText : RichTextItemResponse
) : richText is RichTextItemResponseCommon & TextRichTextItemResponse
Implementation: Returns true if richText.type === "text".
Example:
const page = await notion . pages . retrieve ({ page_id: "page-id" })
if ( isFullPage ( page )) {
const titleProp = page . properties . Name
if ( titleProp . type === "title" ) {
for ( const richText of titleProp . title ) {
if ( isTextRichTextItemResponse ( richText )) {
console . log ( richText . text . content )
console . log ( richText . text . link )
}
}
}
}
isEquationRichTextItemResponse
function isEquationRichTextItemResponse (
richText : RichTextItemResponse
) : richText is RichTextItemResponseCommon & EquationRichTextItemResponse
Implementation: Returns true if richText.type === "equation".
Example:
for ( const richText of content ) {
if ( isEquationRichTextItemResponse ( richText )) {
console . log ( "Equation:" , richText . equation . expression )
}
}
isMentionRichTextItemResponse
function isMentionRichTextItemResponse (
richText : RichTextItemResponse
) : richText is RichTextItemResponseCommon & MentionRichTextItemResponse
Implementation: Returns true if richText.type === "mention".
Example:
for ( const richText of content ) {
if ( isMentionRichTextItemResponse ( richText )) {
console . log ( "Mention type:" , richText . mention . type )
if ( richText . mention . type === "user" ) {
console . log ( "User ID:" , richText . mention . user . id )
}
}
}
Combining Type Guards
Type guards work well together for complex filtering:
const searchResults = await notion . search ({})
for ( const result of searchResults . results ) {
if ( isFullPage ( result )) {
console . log ( "Page:" , result . url )
} else if ( isFullDatabase ( result )) {
console . log ( "Database:" , result . title )
}
}
Best Practices
Always use type guards before accessing full properties
Properties like url, created_time, and type-specific fields only exist on full objects. Use type guards to avoid runtime errors: // Bad - might throw error
console . log ( response . url )
// Good - type-safe
if ( isFullPage ( response )) {
console . log ( response . url )
}
Type guards enable autocomplete
After using a type guard, TypeScript will provide full autocomplete for the narrowed type, making development easier and catching errors early.
Handle both full and partial cases
Always consider what to do when an object is partial: if ( isFullUser ( user )) {
console . log ( user . name )
} else {
console . log ( "User details not available" )
}
Type Definitions
All type guard functions use TypeScript’s is operator for type predicates, which tells TypeScript to narrow the type in the if block:
type ObjectResponse =
| PageObjectResponse
| PartialPageObjectResponse
| DataSourceObjectResponse
| PartialDataSourceObjectResponse
| DatabaseObjectResponse
| PartialDatabaseObjectResponse
| BlockObjectResponse
| PartialBlockObjectResponse
The type guards check runtime properties to determine which variant you have, giving you type safety at both compile time and runtime.