避免在 switch 内进行打字稿转换

2024-04-02

考虑以下代码:

interface FooBarTypeMap {
  FOO: FooInterface;
  BAR: BarInterface;
}

type FooBarTypes = "FOO" | "BAR";

export interface FooBarAction<T extends FooBarTypes> {
  type: T;
  data: FooBarTypeMap[T];
}

const doSomthingBasedOnType = (action: FooBarAction<FooBarTypes>): void => {
  switch (action.type) {
    case "FOO":
      FooAction((action as FooBarAction<"FOO">));
  }
};

const FooAction = (action: FooBarAction<"FOO">): void => {
  //do something with action.data
};

现在我想避免如 doSomthingBasedOnType 中所示的转换(操作为 FooBarAction),因为接口使其成为此开关内唯一的可能性,这正是定义。我可以在代码中更改一些内容才能使其正常工作,还是这只是 TypeScript 中的一个错误?


你需要转型FooBarAction进入一个受歧视的联盟。目前您的版本FooBarAction不是很严格,同时type必须是其中之一"FOO" | "BAR" and data必须是其中之一FooBarTypeMap[FooBarTypes] = FooInterface | BarInterface两者之间没有关系。所以这可以被允许:

let o : FooBarAction2<FooBarTypes> = {
  type: "BAR",
  data: {} as FooInterface
}

受歧视的联合版本将如下所示:

export type FooBarAction = {
  type: "FOO";
  data: FooInterface;
} | {
  type: "BAR";
  data: BarInterface;
}

const doSomthingBasedOnType = (action: FooBarAction): void => {
  switch (action.type) {
    case "FOO":
      FooAction(action);
  }
};

// We use extract to get a specific type from the union
const FooAction = (action: Extract<FooBarAction, { type: "FOO" }>): void => {
  //do something with action.data
};

您还可以使用条件类型的分配行为从类型的联合创建联合:

interface FooInterface { foo: number}
interface BarInterface { bar: number}
interface FooBarTypeMap {
  FOO: FooInterface;
  BAR: BarInterface;
}

type FooBarTypes = "FOO" | "BAR";

export type FooBarAction<T extends FooBarTypes> = T extends any ? {
  type: T;
  data: FooBarTypeMap[T];
}: never;


const doSomthingBasedOnType = (action: FooBarAction<FooBarTypes>): void => {
  switch (action.type) {
    case "FOO":
      FooAction(action);
  }
};

const FooAction = (action: FooBarAction<"FOO">): void => {
  //do something with action.data
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

避免在 switch 内进行打字稿转换 的相关文章

随机推荐