简体   繁体   English

用于处理数据库架构默认值的 Typescript 实用程序类型

[英]Typescript Utility type to handle database schema defaults

I'm looking for a way to type default and virtual (aka. auto generated from other values) values for a database schema.我正在寻找一种方法来为数据库模式键入默认值和虚拟值(也就是从其他值自动生成)值。 The idea is to use an utility type to automatically convert a schema for insertion (props with defaults or generated by virtuals aren't required) and on the other side as a query result (eg. we are sure that these fields will be populated by defaults or other "virtual"-like settings so they can be flagged as NonNullable ).这个想法是使用实​​用程序类型来自动转换模式以进行插入(不需要具有默认值或由虚拟生成的道具),另一方面作为查询结果(例如,我们确定这些字段将由默认值或其他NonNullable “虚拟”的设置,以便将它们标记为NonNullable )。

So something like that if we simplify typings to a single prop:因此,如果我们将类型简化为单个 prop:

type WithDefault<T> = T;
// Mark prop as optional
type Input<T> = T extends WithDefault<infer T> ? T | undefined : T;

The obvious issue with that is that there is no difference between Input<WithDefault> and Input.一个明显的问题是 Input<WithDefault> 和 Input 之间没有区别。 Any idea of something that could help achieve a pattern like that?有什么想法可以帮助实现这样的模式吗? Ending up with a schema like:以如下模式结束:

type User = {
  firstName: string
  lastName: string
  fullName: WithDefault<string>
}

And being able to switch back and forth to an insert-able schema to a read-able schema.并且能够在可插入模式和可读模式之间来回切换。

The problem - as you say - is that the types are structurally equivalent, so TS treats them the same.问题 - 正如你所说 - 是类型在结构上是等效的,所以 TS 对待它们是一样的。

You can tag it with some property with type never to distinguish between the two.你可以用一些带有 type never 的属性来标记它,以区分两者。 The downside is that you're adding a property that needs to not exist, but you can mitigate this by using a Symbol as it is guaranteed to be unique.缺点是您添加了一个不需要存在的属性,但是您可以通过使用 Symbol 来缓解这种情况,因为它保证是唯一的。

Code below (TS playground link here ):下面的代码(TS 游乐场链接在这里):

const __hasDefault = Symbol('__hasDefault');

type WithDefault<T> = T & { [__hasDefault]: never }

type User = {
  firstName: string
  lastName: string
  fullName: WithDefault<string>
}

type ConvertSchema<S extends object> = {
  [key in keyof S]: S[key] extends WithDefault<infer T> ? T | undefined : S[key];
}

type result = ConvertSchema<User>;

This gives you the following result - is that what you were looking for?这为您提供了以下结果 - 这是您要找的吗?

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM