Skip to content

Field 与 Type ​

Schema 条目描述一个逻辑属性。Model 会把它编译成 Field,并由 Field Type 负责解析、存储转换、比较和 JSON 转换。

字段定义 ​

typescript
interface SchemaFieldDefinition {
  readonly name: string;
  column?: string;
  type?: FieldTypeLike;
  validators?: FieldValidator<never> | readonly FieldValidator<never>[];
  allowNull?: boolean;
  primaryKey?: boolean;
  autoIncrement?: boolean;
  defaultValue?: DataValue;
}

interface FieldDefinition<
  Name extends string = string,
  FieldTypeDefinition extends FieldTypeLike = FieldTypeLike,
> {
  readonly name: Name;
  column?: string;
  type?: FieldTypeDefinition;
  validators?:
    | FieldValidator<FieldTypeValue<FieldTypeDefinition>>
    | readonly FieldValidator<FieldTypeValue<FieldTypeDefinition>>[];
  allowNull?: boolean;
  primaryKey?: boolean;
  autoIncrement?: boolean;
  defaultValue?: FieldTypeValue<FieldTypeDefinition>;
}

type SchemaDefinition = readonly SchemaFieldDefinition[];

SchemaFieldDefinition 是任意 Schema 条目都满足的宽泛结构;需要单独声明可复用的字段并保留具体字段名和 Field Type 时,使用 FieldDefinition。多数业务代码直接把数组字面量传给 define(),让 TypeScript 推断即可。

属性默认值说明
name必填逻辑字段名
columnname存储列名
typeType.String值转换契约
validators[]一个或多个校验器
allowNullfalse是否允许 null
primaryKeyfalse是否参与主键查询和行定位
autoIncrementfalse是否由数据库生成
defaultValueType 默认值build() 未传字段时复制的值

直接传给 define() 的普通数组字面量会保留字段级推断。

校验器 ​

typescript
type FieldValidator<Value> = (
  value: Value,
) => string | void | Promise<string | void>;

返回空字符串或 undefined 表示通过;非空字符串会成为错误信息。校验器的 this 是 Model。

typescript
class Field<Definition extends SchemaFieldDefinition = SchemaFieldDefinition> {
  readonly options: Readonly<Definition>;
  readonly name: Definition['name'];
  readonly column: string;
  readonly type: FieldTypeFromDefinition<Definition>;
  readonly validators: readonly FieldValidator<
    FieldDefinitionNonNullValue<Definition>
  >[];
  readonly allowNull: boolean;
  readonly primaryKey: boolean;
  readonly autoIncrement: boolean;
  readonly default: FieldDefinitionValue<Definition> | undefined;
  readonly defaultValue: FieldDefinitionValue<Definition> | undefined;
  readonly needQuotes: boolean;

  parse(
    value: FieldDefinitionStorageValue<Definition>,
  ): FieldDefinitionValue<Definition>;
  restore(
    value: FieldDefinitionValue<Definition>,
  ): FieldDefinitionStorageValue<Definition>;
  readonly equal: (
    left: FieldDefinitionValue<Definition>,
    right: FieldDefinitionValue<Definition>,
  ) => boolean;
  toJSON(
    value: FieldDefinitionValue<Definition>,
  ): FieldDefinitionJsonValue<Definition>;
}

内置 Type ​

typescript
type StringStorageValue = string | number | bigint | boolean | null | undefined;
type BooleanStorageValue = string | number | boolean | null | undefined;
type NumberStorageValue = string | number;
type JsonStorageValue = string | JsonValue;
type DatetimeStorageValue = moment.MomentInput;
Typeparse() 输入应用值restore() 输出JSON 值
Type.StringStringStorageValuestringstringstring
Type.BooleanBooleanStorageValuebooleannumberboolean
Type.IntegerNumberStorageValuenumbernumbernumber
Type.FloatNumberStorageValuenumbernumbernumber
Type.JsonJsonStorageValueJsonValuestringJsonValue
Type.DatetimeDatetimeStorageValueDatestringstring

自定义 Field Type ​

typescript
type FieldType<Value, StorageValue = Value, JsonValue = Value> = {
  name?: string;
  needQuotes?: boolean;
  defaultValue?: Value;
  parse(value: StorageValue): Value;
  restore(value: Value): StorageValue;
  equal?(left: Value, right: Value): boolean;
  toJSON?(value: Value): JsonValue;
};

TypeScript 会检查 parse()、restore()、equal() 与 toJSON() 的值类型是否一致。行推断可使用 RowFromSchema、JsonRowFromSchema、PrimaryKeyNames 和各类 FieldDefinition*Value 辅助类型。

类型展开 ​

typescript
type RowFromSchema<Schema extends SchemaDefinition> = {
  [Definition in Schema[number] as Definition['name']]:
    FieldDefinitionValue<Definition>;
};

type JsonRowFromSchema<Schema extends SchemaDefinition> = {
  [Definition in Schema[number] as Definition['name']]:
    FieldDefinitionJsonValue<Definition>;
};

type PrimaryKeyNames<Schema extends SchemaDefinition> = Extract<
  Schema[number],
  { readonly primaryKey: true }
>['name'];

Released under the MIT License.