typescript - TypeScript 中类型之间的映射

标签 typescript sequelize.js

当我在 TypeScript 中定义一个 Sequelize 模式时,我必须为 Sequelize 生成一个运行时类型,为 TypeScript 生成一个静态类型:

import * as Sequelize from 'sequelize';
const sequelize = new Sequelize('database', 'username', 'password');

// Sequelize Schema
const userSchema = {
  username: Sequelize.STRING,
  birthday: Sequelize.DATE
};

// TypeScript type
interface UserType {
  username: string;
  birthday: Date;
}

const User = sequelize.define<Sequelize.Instance<UserType>, UserType>('user', userSchema);

没有办法定义运行时 Sequelize 模式。但理想情况下,可以从它派生 TypeScript 类型以减少重复。

查看 DefinitelyTyped definitions对于 sequelize 4,Sequelize.STRINGSequelize.DATE 分别有不同的类型:DataTypeStringDataTypeNumber。那么也许可以映射类型?

您可以使用函数重载映射各个类型:

declare function mapTypes(x: typeof Sequelize.NUMBER): number;
declare function mapTypes(x: typeof Sequelize.DATE): Date;

let foo = mapTypes(Sequelize.NUMBER);  // foo has type number!

但不清楚如何将 typeof userSchema 映射到完整的 UserType 接口(interface)。这感觉就像 TypeScript 2.1 中的映射类型功能,但这并不完全有效:

type UserSchemaT = typeof userSchema;
type UserType = {[K in keyof UserSchemaT]: typeof mapTypes(K)};
                                                          ~~~
                                                       // [ts] Cannot find name 'K'.

是否可以通过使用 TypeScript 从一种类型映射到另一种类型来构建新类型?我可以从架构对象的类型生成接口(interface)类型吗?

最佳答案

sequelize API 有 changed considerably在提出这个问题后的三年里。但是为了我自己结束循环,这正是 conditional types 的那种映射。旨在让您做到。

以下是您如何更新问题中的示例以从架构值生成 UserType 类型。

import Sequelize, {DataTypes} from 'sequelize';
const sequelize = new Sequelize('database', 'username', 'password');

// This is a union of the TypeScript types for all possible sequelize data types.
type SequelizeDataTypes = DataTypes[keyof DataTypes];

// Map from Sequelize types to TypeScript types for a single value.
type SequelizeToTs<T extends SequelizeDataTypes> =
  T extends typeof Sequelize.NUMBER ? number :
  T extends typeof Sequelize.STRING ? string :
  T extends typeof Sequelize.DATE ? Date :
  // ...
  never;

// Map between types for a full instance.
type TypeForSchema<T extends Record<string, SequelizeDataTypes>> = {
  [K in keyof T]: SequelizeToTs<T[K]>;
};

// Sequelize Schema
const userSchema = {
  username: Sequelize.STRING,
  birthday: Sequelize.DATE
};

type UserType = TypeForSchema<typeof userSchema>;
// type UserType = {
//   username: string;
//   birthday: Date;
// }

const User = sequelize.define<Sequelize.Instance<UserType>, UserType>('user', userSchema);

关于typescript - TypeScript 中类型之间的映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42520459/

相关文章:

typescript - 如何使用 TypeScript 从 cloudformation 获取可用堆栈的列表?

javascript - 简单的 React 计数器不起作用,console.log 也不能使用State 变量吗?

node.js - sequelize 如何在 Model.update 中引用实例

sql - 如何使用postgres获取日期

java - 从服务传递到组件的 Angular 错误消息

typescript - 确保类型约束按预期工作而不会出现回归

javascript - 如何从类中隐藏构造函数之外的方法也被返回?

node.js - Sequelize - 外键关系 - 别名问题

javascript - 什么时候使用await?

Javascript:SyntaxError:await 仅在异步函数中有效