Home

Typescript Support

supabase-js has TypeScript support for type inference, autocompletion, type-safe queries, and more.

With TypeScript, supabase-js detects things like not null constraints and generated columns. Nullable columns are typed as T | null when you select the column. Generated columns will show a type error when you insert to it.

supabase-js also detects relationships between tables. A foreign table with one-to-many relationship is typed as T[]. Likewise, a foreign table with many-to-one relationship is typed as T | null.

Generating types#

You can use the Supabase CLI to generate the types. You can also generate the types from the dashboard.

Terminal

_10
supabase gen types typescript --project-id abcdefghijklmnopqrst > database.types.ts

These types are generated from your database schema. Given a table public.movies, the generated types will look like:


_10
create table public.movies (
_10
id bigint generated always as identity primary key,
_10
name text not null,
_10
data jsonb null
_10
);

./database.types.ts

_25
export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[]
_25
_25
export interface Database {
_25
public: {
_25
Tables: {
_25
movies: {
_25
Row: { // the data expected from .select()
_25
id: number
_25
name: string
_25
data: Json | null
_25
}
_25
Insert: { // the data to be passed to .insert()
_25
id?: never // generated columns must not be supplied
_25
name: string // `not null` columns with no default must be supplied
_25
data?: Json | null // nullable columns can be omitted
_25
}
_25
Update: { // the data to be passed to .update()
_25
id?: never
_25
name?: string // `not null` columns are optional on .update()
_25
data?: Json | null
_25
}
_25
}
_25
}
_25
}
_25
}

Using type definitions#

You can supply the type definitions to supabase-js like so:

./index.tsx

_10
import { createClient } from '@supabase/supabase-js'
_10
import { Database } from './database.types'
_10
_10
const supabase = createClient<Database>(
_10
process.env.SUPABASE_URL,
_10
process.env.SUPABASE_ANON_KEY
_10
)

Helper types#

You can use the following helper types to make the TypeScript support easier to use.

Sometimes the generated types are not what you expect. For example, a view's column may show up as nullable when you expect it to be not null. Using type-fest, you can override the types like so:

./database-generated.types.ts

_10
export type Json = // ...
_10
_10
export interface Database {
_10
// ...
_10
}

./database.types.ts

_19
import { MergeDeep } from 'type-fest'
_19
import { Database as DatabaseGenerated } from './database-generated.types'
_19
export { Json } from './database-generated.types'
_19
_19
export type Database = MergeDeep<
_19
DatabaseGenerated,
_19
{
_19
public: {
_19
Views: {
_19
movies_view: {
_19
Row: {
_19
// id is a primary key in public.movies, so it must be `not null`
_19
id: number
_19
}
_19
}
_19
}
_19
}
_19
}
_19
>

It's convenient to have shorthands for your most-used types.

./database.types.ts

_10
export type Tables<T extends keyof Database['public']['Tables']> = Database['public']['Tables'][T]['Row']
_10
export type Enums<T extends keyof Database['public']['Enums']> = Database['public']['Enums'][T]
_10
// etc.

./index.ts

_10
// Before 😕
_10
let movie: Database['public']['Tables']['movies']['Row'] = // ...
_10
_10
// After 😍
_10
let movie: Tables<'movies'>

supabase-js always returns a data object (for success), and an error object (for unsuccessful requests).

These helper types provide the result types from any query:


_10
import { PostgrestError } from '@supabase/supabase-js'
_10
_10
export type DbResult<T> = T extends PromiseLike<infer U> ? U : never
_10
export type DbResultOk<T> = T extends PromiseLike<{ data: infer U }> ? Exclude<U, null> : never
_10
export type DbResultErr = PostgrestError


_10
const query = supabase.from('movies').select(`id, title`)
_10
const movies: DbResult<typeof query> = await query