jer*_*rfp 3 typescript react-redux
我看到一些我不理解的非常奇怪的 TypeScript 行为。这是场景:
我有三个不同的界面来描述一个事件。他们看起来像这样
interface ReceiveMessageEvent {
event: 'receive-message';
payload: {
action: 'receive-message';
businessSMSId: number;
message: {
businessSMSId: number;
from: string;
to: string;
};
};
}
interface ReadMessageEvent {
event: 'read-message';
payload: {
action: 'read-message';
businessSMSId: number;
customerNumber: string;
inboxNumber: string;
};
}
interface SetThreadsEvent {
event: 'set-threads';
threads: any[];
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,所有三个接口都有event一个特定字符串的属性,这意味着只能有三个可能的选项,“receive-message”、“read-message”或“set-threads”。这很重要,因为接下来我有一个 switch 语句,其中的情况是此事件属性:
switch (action.payload.event) {
case 'receive-message':
// ...
case 'read-message':
// ...
case 'set-threads':
// ...
}
Run Code Online (Sandbox Code Playgroud)
因此,由于 case 是事件属性,我希望 TypeScript 能够根据我们所处的情况知道其余数据的形状。现在,是否正确执行此操作(正如我所期望的那样),除了在一个特定的场景中,这就是我的困惑所在。这种情况是当我在 .filter 方法的回调函数内部时。
例如:
switch (action.payload.event) {
case 'receive-message':
// This is correct and has no errors
const test = action.payload.payload.message.to
// This is giving me a TS error, even though I'm accessing the exact same property
// As in the line above
myArray.filter((thread) => thread.property === action.payload.payload.message.to)
^^^^^^^^ TS error here
case 'read-message':
// ...
case 'set-threads':
// ...
}
Run Code Online (Sandbox Code Playgroud)
上面例子中的确切错误是这样的:
Property 'payload' does not exist on type 'ReceiveMessageEvent | ReadMessageEvent | SetThreadsEvent'.
Property 'payload' does not exist on type 'SetThreadsEvent'.
Run Code Online (Sandbox Code Playgroud)
一旦我进入回调函数,Typescript 就好像失去了它的类型知识。该代码实际上确实按照预期工作,只是 TypeScript 告诉我有错误,尽管似乎没有错误。
最后我会注意到,我可以像这样进行一些转换,然后错误就会消失,尽管我不想这样做,除非我绝对必须这样做):
switch (action.payload.event) {
case 'receive-message':
myArray.filter((thread) => thread.property === (action.payload as ReceiveMessageEvent).payload.message.to)
case 'read-message':
// ...
case 'set-threads':
// ...
}
Run Code Online (Sandbox Code Playgroud)
这种行为是否有原因,或者这可能是 TypeScript 中的错误?
一旦我进入回调函数,Typescript 就好像失去了它的类型知识
是的,就是这样。而这种行为是故意的。或者至少,这是打字稿能做到的最好的。
问题是打字稿不知道回调函数何时被调用。你和我都知道.filter回调将被同步调用,中间没有任何内容,但并非所有回调都是如此。例如,in中的回调setTimeout将被异步调用。
类型信息无法识别它是否是同步的,因此打字稿必须假设最坏的情况:异步。如果异步调用回调,则任何任意代码都可能在回调之前运行,因此您为缩小类型范围所做的检查可能不再准确。一些代码可能同时改变了属性。
最简单的解决方法通常是在非回调代码中将您关心的值分配给 const,然后在回调代码中引用该 const。使用 const,打字稿可以假设它尚未被重新分配。
case 'receive-message':
const test = action.payload.payload.message.to
myArray.filter((thread) => thread.property === test)
// OR:
case 'receive-message':
const payload = action.payload.payload
myArray.filter((thread) => thread.property === payload.message.to)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
233 次 |
| 最近记录: |