简体   繁体   English

没有类型保护的打字稿判别联合

[英]Typescript Discriminated Union without type guard

The code below results in the error:下面的代码导致错误:

TS2322: Type 'RhinoData | HippoData' is not assignable to type 'RhinoData & HippoData'.
  Type 'RhinoData' is not assignable to type 'RhinoData & HippoData'.
    Property 'bar' is missing in type 'RhinoData' but required in type 'HippoData'.

The hope was that the AnimalPayload type provides enough information to guarantee that the assignment is legal.希望AnimalPayload类型提供足够的信息来保证分配是合法的。 Is there a way to accomplish this in such a way that setAnimalState does not have to worry about specific types?有没有办法以setAnimalState不必担心特定类型的方式来完成此操作?

enum Animal {
  RHINO = 'RHINO',
  HIPPO = 'HIPPO',
}

interface RhinoData {
  foo: string,
}

interface HippoData {
  bar: string,
}

interface AnimalState {
  [Animal.RHINO]: RhinoData,
  [Animal.HIPPO]: HippoData,
}

type AnimalPayload = {
  type: Animal.RHINO,
  data: RhinoData,
} | {
  type: Animal.HIPPO,
  data: HippoData,
}

const state: AnimalState = {
  [Animal.RHINO]: null,
  [Animal.HIPPO]: null,
};

const setAnimalState = (payload: AnimalPayload) => {
  state[payload.type] = payload.data;
};

It sounds like typescript can't infer the fact that the type of payload.type is constrained by the type of AnimalState .这听起来像打字稿不能推断类型的事实payload.type由类型约束AnimalState Using mapped types can fix your problem here by making that relationship explicit.使用映射类型可以通过使这种关系显式来解决您的问题。

enum Animal { RHINO = "RHINO", HIPPO = "HIPPO" }

interface RhinoData {
  foo: string,
}

interface HippoData {
  bar: string,
}

interface AnimalState {
  [Animal.RHINO]: RhinoData | null,
  [Animal.HIPPO]: HippoData | null,
}

type AnimalPayload<T extends Animal> = {
  type: T
  data: AnimalState[T],
}

const state: AnimalState = {
  [Animal.RHINO]: null,
  [Animal.HIPPO]: null,
};

const setAnimalState = <T extends Animal>(payload: AnimalPayload<T>) => {
  state[payload.type] = payload.data;
};

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

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