首页 > 解决方案 > 如何区分交叉口

问题描述

打字稿游乐场

鉴于这种事件的结合:

type Events = 
  | { type: 'CREATE'; data: { foo: string } }
  | { type: 'READ'; uuid: string } 
  | { type: 'UPDATE'; data: { foo: string; uuid: string } };

我制作了处理事件的函数,还收集了一张地图:

const processors: Processors<Events> = {
  CREATE: (event) => {
    console.log(event.data.foo);
  },
  READ: (event) => {
    console.log(event.uuid);
  },
  UPDATE: (event) => {
    console.log(event.data.uuid);
  },
}

Processors<Event>类型并不复杂并且可以预见地工作:

type Processors<E extends EventObject> =
  { [T in E['type']]: (event: Extract<E, { type: T}>) => void };

尝试使用这些函数处理事件时遇到问题:

function(event: Events) {
  const receiver = processors[event.type]; //  this produces (event: never) => void 
  receiver(event);
           ^^^^^ error
}

接收器的参数类型是intersection因为它来自类型中的逆变位置Processors<Event>

receiver(event: 
  { type: 'CREATE'; data: { foo: string } } &
  { type: 'READ'; uuid: string } &
  { type: 'UPDATE'; data: { foo: string; uuid: string } }
);

我假设事件联合不可分配给事件交集。

如果我歧视工会,问题就消失了:

if (event.type === 'CREATE') {
  const receiver = processors[event.type] 
  receiver(event);
}

但这越来越不合理,因为我们知道事件在任何给定时间总是只有一种类型。

没有类型转换是否可以解决问题?就好像您可以将交集转换为并集,区分交集。

function(event: Events) {
  const receiver = processors[event.type]; //  this produces (event: never) => void 
  receiver(event);
           ^^^^^ How to solve the problem without useless and redundant code?
}

标签: typescript

解决方案


推荐阅读