当我在 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.STRING
和 Sequelize.DATE
分别有不同的类型:DataTypeString
和 DataTypeNumber
。那么也许可以映射类型?
您可以使用函数重载映射各个类型:
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/