Typescript动态创建界面 [英] Typescript dynamically create interface

查看:123
本文介绍了Typescript动态创建界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用简单模式在对象中定义数据库模式:

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类型的方法(分别为stringnumber):

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆