没有类型保护的Typescript区分并集

没有类型保护的Typescript区分并集,typescript,Typescript,以下代码导致错误: 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 'Hi

以下代码导致错误:

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'.
希望AnimalPayload类型提供足够的信息来保证该分配是合法的。有没有一种方法可以让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;
};

听起来typescript无法推断payload.type的类型受AnimalState类型的约束。使用映射类型可以通过使关系显式化来解决您的问题

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;
};