[英]Typescript dynamically create interface
我使用简单模式在对象中定义数据库模式:
{
name: 'string',
age: 'integer',
...
}
是否有可能从这个对象创建一个接口或类,所以我不必两次输入所有内容?
您可以这样做,但它可能比它的价值更麻烦,除非您认为您可能正在更改架构。 TypeScript 没有以您想要的方式推断类型的内置方法,因此您必须哄骗它这样做:
首先,定义一种将文字名称'string'
和'integer'
映射到它们所代表的 TypeScript 类型(大概分别是string
和number
)的方法:
type MapSchemaTypes = {
string: string;
integer: number;
// others?
}
type MapSchema<T extends Record<string, keyof MapSchemaTypes>> = {
-readonly [K in keyof T]: MapSchemaTypes[T[K]]
}
现在,如果您可以使用您指定的类型的适当类型的架构对象,并从中获取关联的类型:
const personSchema = {name: 'string', age: 'integer'};
type Person = MapSchema<typeof personSchema>; // ERROR
糟糕,问题是personSchema
被推断为{name: string; age: string}
{name: string; age: string}
而不是所需的{name: 'string'; age: 'integer'}
{name: 'string'; age: 'integer'}
。 您可以使用类型注释修复它:
const personSchema: { name: 'string', age: 'integer' } = { name: 'string', age: 'integer' };
type Person = MapSchema<typeof personSchema>; // {name: string; age: number};
但现在感觉就像你在重复自己。 幸运的是,有一种方法可以强制它推断正确的类型:
function asSchema<T extends Record<string, keyof MapSchemaTypes>>(t: T): T {
return t;
}
const personSchema = asSchema({ name: 'string', age: 'integer' }); // right type now
type Person = MapSchema<typeof personSchema>; // {name: string; age: number};
2020-06 更新:在更新的 TS 版本中,您可以使用const
断言来获得相同的结果:
const personSchema = { name: 'string', age: 'integer' } as const;
type Person = MapSchema<typeof personSchema>;
那个有效!
在 Typescript Playground 上查看它的实际效果。 希望有所帮助; 祝你好运!
我认为您不能声明动态接口。 但是,您可以为具有已知属性的对象创建类型。
您可以创建一个将字符串文字映射到实际类型的对象,例如'integer' => number
,但这与问题无关。 我不知道您使用的是什么框架,但以下示例适用于外观相似的框架:Mongoose。
用户.js
export const UserSchema = mongoose.Schema({
name: String,
value: Number
});
export const Users = mongoose.Model('users', UserSchema);
export type User = { [K in keyof typeof UserSchema]: any } ;
用法:
import { User, Users } from './user';
Users.find({}).exec((err: Error, res: User) => { ... })
返回的结果应该与UserSchema
具有相同的键,但所有值都映射到 any ,因为您仍然需要将字符串文字映射到类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.