生成TypeScript类型
如何为您的API和Supabase库生成类型定义
Supabase API 是从您的数据库自动生成的,这意味着我们可以利用数据库自省功能来生成类型安全的 API 定义。
从项目仪表板生成类型
Supabase 允许您直接从项目仪表板生成并下载 TypeScript 类型定义。
使用 Supabase CLI 生成类型
Supabase CLI 是一个单二进制 Go 应用程序,提供了设置本地开发环境所需的一切功能。
您可以通过 npm 或其他支持的包管理器安装 CLI。CLI 的最低要求版本是 v1.8.1。
1npm i supabase@">=1.8.1" --save-dev
使用您的个人访问令牌登录:
1npx supabase login
在生成类型之前,请确保初始化您的 Supabase 项目:
1npx supabase init
为您的项目生成类型以创建 database.types.ts
文件:
1npx supabase gen types typescript --project-id "$PROJECT_REF" --schema public > database.types.ts
如果是本地开发环境:
1npx supabase gen types typescript --local > database.types.ts
这些类型是从您的数据库模式生成的。假设有一个 public.movies
表,生成的类型将如下所示:
12345create table public.movies ( id bigint generated always as identity primary key, name text not null, data jsonb null);
12345678910111213141516171819202122232425262728export type = string | number | boolean | null | { [: string]: | undefined } | []export interface { : { : { : { : { // .select() 方法期望返回的数据结构 : number : string : | null } : { // 传递给 .insert() 方法的数据 ?: never // 不能提供自动生成的列 : string // 没有默认值的 `not null` 列必须提供 ?: | null // 可为空的列可以省略 } : { // 传递给 .update() 方法的数据 ?: never ?: string // `not null` 列在更新时是可选的 ?: | null } } } }}
使用 TypeScript 类型定义
您可以像这样为 supabase-js
提供类型定义:
1234import { createClient } from '@supabase/supabase-js'import { Database } from './database.types'const supabase = createClient<Database>(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY)
表和连接辅助类型
您可以使用以下辅助类型来简化生成的 TypeScript 类型的使用。
有时生成的类型可能不符合预期。例如,视图中的列可能显示为可空(nullable),而您预期它应该是 not null
。使用 type-fest,您可以像这样覆盖类型:
12345export type Json = // ...export interface Database { // ...}
1234567891011121314151617181920import { MergeDeep } from 'type-fest'import { Database as DatabaseGenerated } from './database-generated.types'export { Json } from './database-generated.types'// 覆盖视图中特定列的类型:export type Database = MergeDeep< DatabaseGenerated, { public: { Views: { movies_view: { Row: { // id 是 public.movies 的主键,因此必须为 `not null` id: number } } } } }>
要使用 MergeDeep
,请在您的 tsconfig.json
中将 compilerOptions.strictNullChecks
设置为 true
。
您还可以根据需要覆盖单个成功响应的类型:
123456789// 部分类型覆盖允许您只覆盖结果中的部分属性const { data } = await supabase.from('countries').select().overrideTypes<Array<{ id: string }>>()// 若要完全替换原始返回类型,请使用第二个参数 `{ merge: false }`const { data } = await supabase .from('countries') .select() .overrideTypes<Array<{ id: string }>, { merge: false }>()// 与 `maybeSingle` 或 `single` 一起使用const { data } = await supabase.from('countries').select().single().overrideTypes<{ id: string }>()
类型简写
生成的类型提供了访问表和枚举的简写方式。
1234567import { Database, Tables, Enums } from "./database.types.ts";// 之前 😕let movie: Database['public']['Tables']['movies']['Row'] = // ...// 之后 😍let movie: Tables<'movies'>
复杂查询的响应类型
supabase-js
总是返回一个 data
对象(表示成功)和一个 error
对象(表示请求失败)。
这些辅助类型提供了任何查询的结果类型,包括数据库连接操作的嵌套类型。
给定以下包含城市与国家关系的模式:
12345678910create table countries ( "id" serial primary key, "name" text);create table cities ( "id" serial primary key, "name" text, "country_id" int references "countries");
我们可以这样获取嵌套的 CountriesWithCities
类型:
123456789101112131415import { QueryResult, QueryData, QueryError } from '@supabase/supabase-js'const countriesWithCitiesQuery = supabase.from('countries').select(` id, name, cities ( id, name )`)type CountriesWithCities = QueryData<typeof countriesWithCitiesQuery>const { data, error } = await countriesWithCitiesQueryif (error) throw errorconst countriesWithCities: CountriesWithCities = data
使用 GitHub Actions 自动更新类型定义
保持类型定义与数据库同步的一种方法是设置定时运行的 GitHub Action。
在您的 package.json
中添加以下脚本,以便使用 npm run update-types
运行:
1"update-types": "npx supabase gen types --lang=typescript --project-id \"$PROJECT_REF\" > database.types.ts"
创建 .github/workflows/update-types.yml
文件并添加以下代码片段来定义 Action 及环境变量。该脚本将每晚提交新的类型变更到您的代码库。
1234567891011121314151617181920212223242526272829303132333435363738394041name: 更新数据库类型on: schedule: # 设置 Action 每天运行。您可以修改此配置以调整运行频率 - cron: '0 0 * * *'jobs: update: runs-on: ubuntu-latest permissions: contents: write env: SUPABASE_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} PROJECT_REF: <your-project-id> steps: - uses: actions/checkout@v4 with: persist-credentials: false fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version: 22 - run: npm run update-types - name: 检查文件变更 id: git_status run: | echo "status=$(git status -s)" >> $GITHUB_OUTPUT - name: 提交变更 if: ${{contains(steps.git_status.outputs.status, ' ')}} run: | git add database.types.ts git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" git commit -m "更新数据库类型定义" -a - name: 推送变更 if: ${{contains(steps.git_status.outputs.status, ' ')}} uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} branch: ${{ github.ref }}
或者,您也可以使用社区维护的 GitHub Action:generate-supabase-db-types-github-action
。