Become a Gold Sponsor

定义自定义类型的常用方法

示例

查看 customType 定义如何工作的最佳方法是检查如何使用 Drizzle ORM 中的 customType 函数定义 postgres 和 mysql 中现有的数据类型。

Postgres 数据类型
MySql 数据类型

Serial

import { customType } from 'drizzle-orm/pg-core';

const customSerial = customType<{ data: number; notNull: true; default: true }>(
  {
    dataType() {
      return 'serial';
    },
  },
);

Text

import { customType } from 'drizzle-orm/pg-core';

const customText = customType<{ data: string }>({
  dataType() {
    return 'text';
  },
});

Boolean

import { customType } from 'drizzle-orm/pg-core';

const customBoolean = customType<{ data: boolean }>({
  dataType() {
    return 'boolean';
  },
});

Jsonb

import { customType } from 'drizzle-orm/pg-core';

const customJsonb = <TData>(name: string) =>
  customType<{ data: TData; driverData: string }>({
    dataType() {
      return 'jsonb';
    },
    toDriver(value: TData): string {
      return JSON.stringify(value);
    },
  })(name);

Timestamp

import { customType } from 'drizzle-orm/pg-core';

const customTimestamp = customType<
  {
    data: Date;
    driverData: string;
    config: { withTimezone: boolean; precision?: number };
  }
>({
  dataType(config) {
    const precision = typeof config.precision !== 'undefined'
      ? ` (${config.precision})`
      : '';
    return `timestamp${precision}${
      config.withTimezone ? ' with time zone' : ''
    }`;
  },
  fromDriver(value: string): Date {
    return new Date(value);
  },
});

所有类型的用法与 Drizzle ORM 中定义的函数相同。例如:

const usersTable = pgTable('users', {
  id: customSerial('id').primaryKey(),
  name: customText('name').notNull(),
  verified: customBoolean('verified').notNull().default(false),
  jsonb: customJsonb<string[]>('jsonb'),
  createdAt: customTimestamp('created_at', { withTimezone: true }).notNull()
    .default(sql`now()`),
});

自定义类型定义的 TS 文档

您可以查看 typesparam 定义的 ts-doc。

export type CustomTypeValues = {
  /**
   * 自定义列所需的类型,将推断适当的类型模型
   *
   * 示例:
   *
   * 如果您希望您的列在选择/插入后为 `string` 类型 - 使用 `data: string`。如 `text`,`varchar`
   *
   * 如果您希望您的列在选择/插入后为 `number` 类型 - 使用 `data: number`。如 `integer`
   */
  data: unknown;

  /**
   * 类型助手,表示数据库驱动程序接受特定数据库数据类型的类型
   */
  driverData?: unknown;

  /**
   * {@link CustomTypeParams} `dataType` 生成应使用什么配置类型
   */
  config?: Record<string, unknown>;

  /**
   * 如果您的自定义数据类型应默认不为空,您可以使用 `notNull: true`
   *
   * @example
   * const customSerial = customType<{ data: number, notNull: true, default: true }>({
   *    dataType() {
   *      return 'serial';
   *    },
   * });
   */
  notNull?: boolean;

  /**
   * 如果您的自定义数据类型有默认值,您可以使用 `default: true`
   *
   * @example
   * const customSerial = customType<{ data: number, notNull: true, default: true }>({
   *    dataType() {
   *      return 'serial';
   *    },
   * });
   */
  default?: boolean;
};

export interface CustomTypeParams<T extends CustomTypeValues> {
  /**
   * 用于迁移的数据库数据类型字符串表示
   * @example
   * ```
   * `jsonb`, `text`
   * ```
   *
   * 如果数据库数据类型需要附加参数,您可以从 `config` 参数中使用它们
   * @example
   * ```
   * `varchar(256)`, `numeric(2,3)`
   * ```
   *
   * 要使 `config` 为特定类型,请在 {@link CustomTypeValues} 中使用配置泛型
   *
   * @example
   * 使用示例
   * ```
   *   dataType() {
   *     return 'boolean';
   *   },
   * ```
   * 或
   * ```
   *   dataType(config) {
   *     return typeof config.length !== 'undefined' ? `varchar(${config.length})` : `varchar`;
   *   }
   * ```
   */
  dataType: (config: T['config']) => string;

  /**
   * 可选的映射函数,介于用户输入和驱动程序之间
   * @example
   * 例如,当使用 jsonb 时,我们需要将 JS/TS 对象映射为字符串,然后写入数据库
   * ```
   * toDriver(value: TData): string {
   *   return JSON.stringify(value);
   * }
   * ```
   */
  toDriver?: (value: T['data']) => T['driverData'];

  /**
   * 可选的映射函数,负责将数据从数据库映射到 JS/TS 代码
   * @example
   * 例如,当使用时间戳时,我们需要将字符串日期表示映射为 JS 日期
   * ```
   * fromDriver(value: string): Date {
   *  return new Date(value);
   * },
   * ```
   */
  fromDriver?: (value: T['driverData']) => T['data'];
}