1

我想创建一个通用的 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);
  }
}

this 的泛型是这样的:

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

我想合并这两种情况:

  1. create 和 update 共享相同的接口,其中实体(称为E) id 与属性 name Id。这个 id 是通用的(称为它I),它的类型是I | null | undefined. 该接口因此而扩展MaybeEntity<I>
  2. 创建和更新接受不同的接口。使用 ceate 函数时,它应该接受不存在C extends NotEnity的接口,或者返回一个. 更新只接受必须在的地方IdnullundefinedEE extends Entity<I>IdI

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

export type Id = 'id';
export type Entity<I> = Record<Id, I>;
export type NotEntity = Partial<Record<Id, null>>;
export type MaybeEntity<I> = Partial<Record<Id, I | null >>;

class HttpService<I, E extends MaybeEntity<I>, C extends NotEntity = (E & NotEntity )> {
  create(model: C | E & NotEntity) { }

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

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

2 回答 2

1

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

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);
  }
}
于 2020-11-05T14:39:43.123 回答
1

您的代码中缺少的是三元语句 insave没有理解它所施加的限制,也没有改进and分支model中的类型。truefalse

Typescript 可以理解简单的属性检查条件,但是当你将它们与&&它结合起来时,它就会停止尝试。我们需要将这个多重条件检查提取到它自己的类型保护函数中,并告诉 Typescript 是什么意思trueor false

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如果存在 an 则无法调用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);
  }
}

打字稿游乐场链接

于 2021-01-24T05:23:00.387 回答