微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何编写类型安全的联合类型的保存方法

如何解决如何编写类型安全的联合类型的保存方法

我想创建一个通用的http服务,并且希望有一个类似save(value)方法,该方法在下面调用create(value)update(value)。所不同的是,我想选择配置create接受的值的类型,该值可能与更新值完全不同。

赞:

class HttpService {
  create(model) {
    ...
  }
  update(model) {
    ... 
  }
  save(model) {
    if(model.id === null || model.id === undefined) {
      return this.create(model);
    }
    return this.update(model);
  }
}

此类型的通用类型如下:

class HttpService<I,E,C> {
  create(model: E | C) : E;
  update(model: E) : E;
  save(model: E | C): E;
}

我想合并这两种情况:

  1. 创建和更新共享与属性名称E的实体(称为Id)id相同的接口。该ID是通用的(称为I),其类型为I | null | undefined。因此,此接口扩展了MaybeEntity<I>
  2. 创建和更新接受不同的界面。使用ceate函数时,它应接受C extends NotEnityId不在的null接口undefined并返回一个E。此更新仅接受E extends Entity<I>必须为Id的{​​{1}}

我尝试过这些类型,但是失败了

I

解决方法

您的代码中缺少的是 save 中的三元语句不理解它所施加的限制,并且没有改进 model 中的 true 类型和 false 分支。

Typescript 可以理解简单的属性检查条件,但是当您将它们与 && 结合使用时,它会停止尝试。我们需要将这种多重条件检查提取到它自己的类型保护函数中,并告诉 Typescript truefalse 的含义。

const hasId = <E extends MaybeEntity<any>>( model: E ): model is E & {id: NonNullable<E['id']>} => {
  return 'id' in model && model.id === undefined && model.id === null;
}

现在您允许 C 要求创建所需但不存在于创建对象中的任意属性。这真的有必要吗?可以支持这一点,但需要更高级的检查。

您还说如果存在 create,则无法调用 id。这真的有必要吗,还是可以忽略 id? (例如,如果将现有对象克隆到新 ID)。

假设这两个都不是绝对必要的,这段代码将起作用:

export class HttpService<I,E extends MaybeEntity<I>> {
  create(model: E) { }

  update(model: E & Entity<I>) { }

  save(model: E) {
    return hasId(model)
      ? this.update(model)
      : this.create(model);
  }
}

Typescript Playground Link

,

更新。很抱歉,如果我误解了您的问题。我为Entity创建了一个接口(虽然可能是类型)。我还为NotEntity创建了一个类型,它只是一个没有id的实体。该类使用Entity,然后在保存功能中检查id的类型,如果它是undefined或它的值等于null,那么我们在谈论的不是实体,并且调用保存功能。否则,我们有一个id,我们可以调用update函数。我相信有更好的方法可以做到这一点,但这可能是您自己的初步方法。

export interface Entity<I> {
  id?: I,[key: string]: any
}

export type NotEntity<I> = Omit<Entity<I>,'id'>;

export class HttpService<I,E extends Entity<I>> {
  create(model: NotEntity<I>) {}

  update(model: Entity<I>) {}

  save(model: E) {
    return typeof model.id ===  undefined || model.id === null
      ? this.create(model)
      : this.update(model);
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?