考虑以下代码:
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(使用前将#替换为@)