我有一个函数的类型定义。我将第二个参数的类型定义为以第一个参数的类型为条件,例如:
const FOO = "FOO";
const BAR = "BAR";
let fooPayload = {
zip: "zap"
}
let barPayload = {
cat: "dog"
}
type ActionTypes = typeof FOO | typeof BAR;
interface MyFunction<T extends ActionTypes = ActionTypes> {
(
action: {
type: T;
payload: T extends typeof FOO
? typeof fooPayload
: typeof barPayload;
}
): boolean;
}
MyFunction
接口所引用的函数中包含一个switch语句,该语句基于action.type
进行切换,并根据情况对action.payload
进行操作。这是一个示例:
const myFunction:MyFunction = (action) => {
switch (action.type) {
case FOO:
action.payload.zip = "new zap"
return true
case BAR:
action.payload.cat = "new dog"
return false
default:
return false
}
}
我遇到的问题是Typescript无法正确地从switch语句推断出action.payload
应该是什么。例如,如果action.type
等于“ FOO”,则应该推断action.payload
必须为typeof fooPayload
。而是推断它是typeof fooPayload | typeof barPayload
。
这没有任何意义,因为action.payload
的类型定义基于action.type
的值,并且由于action.payload.zip
在switch语句中被调用,因此只能在action.type
等于“ FOO” 时发生,它应该推断出action.payload
唯一可能的类型是typeof fooPayload
。
我在这里做什么错了?
答案 0 :(得分:0)
我不确定这是导致问题的确切位置,但总的来说,问题是您正在尝试重新发明哪种打字稿已经很好用,窄型联合。
条件是一个非常有趣的功能,但是由于它们是分布式的,因此有时会出现一些意外情况,因为它们超出了定义的范围。
我将以另一种方式实现这一点:
interface Action<T, P> {
type: T,
payload: P
}
type Actions
= Action<typeof FOO, typeof FooPayload>
| Action<typeof BAR, typeof BarPayload>
;
interface MyFunction {
(action: Actions): boolean;
}
不需要条件,并且打字稿将按预期在开关中缩小并集。
答案 1 :(得分:0)
您可以将类型显式传递给Assign语句:
switch (action.type) {
case FOO:
(action.payload as typeof FooPayload).zip = "new zap"
return true
case BAR:
(action.payload as typeof BarPayload).cat = "new dog"
return false
default:
return false
}