Typescript动态创建界面 [英] Typescript dynamically create interface
问题描述
我使用简单模式在对象中定义数据库模式:
I use simple-schema to define DB schemas in an object:
{
name: 'string',
age: 'integer',
...
}
是否可以通过该对象创建接口或类,所以我不必两次键入所有内容?
Is it somehow possible to create an interface or class from this object, so I don't have to type everything twice?
推荐答案
您可以执行此操作,但是除非您认为自己正在更改架构,否则它可能会比值得的麻烦更多. TypeScript没有内置的以您想要的方式推断类型的方法,因此您必须哄骗并哄骗它:
You can do this, but it might be more trouble than it's worth unless you think you might be changing the schema. TypeScript doesn't have built-in ways of inferring types in a way that you want, so you have to coax and cajole it to do so:
首先,定义一种将文字名称'string'
和'integer'
映射到它们表示的TypeScript类型的方法(分别为string
和number
):
First, define a way of mapping the literal names 'string'
and 'integer'
to the TypeScript types they represent (presumably string
and number
respectively):
type MapSchemaTypes = {
string: string;
integer: number;
// others?
}
type MapSchema<T extends Record<string, keyof MapSchemaTypes>> = {
-readonly [K in keyof T]: MapSchemaTypes[T[K]]
}
现在,如果您可以采用适当类型的架构对象(如您指定的架构对象),并从中获取关联的类型:
Now if you can take an appropriately typed schema object like the one you specified, and get the associated type from it:
const personSchema = {name: 'string', age: 'integer'};
type Person = MapSchema<typeof personSchema>; // ERROR
糟糕,问题在于将personSchema
推断为{name: string; age: string}
而不是所需的{name: 'string'; age: 'integer'}
.您可以使用类型注释来解决该问题:
Oops, the problem is that personSchema
is being inferred as {name: string; age: string}
instead of the desired {name: 'string'; age: 'integer'}
. You can fix that with a type annotation:
const personSchema: { name: 'string', age: 'integer' } = { name: 'string', age: 'integer' };
type Person = MapSchema<typeof personSchema>; // {name: string; age: number};
但是现在感觉就像是在重复自己.幸运的是,有一种方法可以强制其推断正确的类型:
But now it feels like you're repeating yourself. Luckily there is a way to force it to infer the proper type:
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};
UPDATE 2020-06:在更新的TS版本中,您可以使用 const
断言以获得相同的结果:
UPDATE 2020-06: in more recent TS versions you can use a const
assertion to get the same result:
const personSchema = { name: 'string', age: 'integer' } as const;
type Person = MapSchema<typeof personSchema>;
那行得通!
请参阅它在行动在打字稿游乐场上.希望能有所帮助;祝你好运!
See it in action on the Typescript Playground. Hope that helps; good luck!
这篇关于Typescript动态创建界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!