我似乎无法匹配函数接受的参数类型和有效负载:

type SelectCase = {
  type: 'selectCase';
}

type UpdateNotification = {
  type: 'updateNotification';
  payload: {
    title: string;
    message: string;
  }
}

type Message = SelectCase | UpdateNotification;

const someFn = <TMessageType extends Message['type']>(
    messageType: TMessageType,
    onMessage: (
        payload?: Extract<Message, { type: TMessageType }> extends {
            payload: infer TPayload;
        }
            ? TPayload
            : undefined
    ) => void
) => {
  const handleMessage = (message: Message) => {
    if(message.type === messageType) {
      // does not work
      onMessage(message.payload);
    }
  }
};

这是一个简化的例子,我有20多种类型的消息.你知道为什么这不管用吗?

我try 了类型谓词和调用签名,但仍然出错.

推荐答案

这里的问题是TypeScrip缺乏对correlated 100 types的直接支持,正如microsoft/TypeScript#30581中所描述的那样.本质上,类型判断器不容易理解判断message.type === messageType应该narrow messageMessage联合的成员,该联合的payload属性可以由onMessage()处理.在该判断之后,message的类型变为correlatedmessageType的类型,而不是具体知道.但是,没有一种简单的方法可以将这样的信息传递给编译器.

通常,您可以像microsoft/TypeScript#47109中描述的那样使用generics和一些类型重构来解决这个问题,但我无法在这里让它工作(如果有人does让它工作,请让我知道).


因此,我认为我们能做的最好的事情是写一个custom type guard function,表示message.type === messageType将适当地缩小message.这里有一种方法:

首先,我将把onMessage()参数的条件类型复制到我们可以重复使用的实用程序类型中:

type CorrespondingPayload<K extends Message['type']> =
    Extract<Message, { type: K }> extends {
        payload: infer TPayload;
    } ? TPayload : undefined

现在,自定义类型的防护函数如下所示:

function sameType<K extends Message['type']>(
    message: Message, messageType: K
): message is Message & { type: K, payload: CorrespondingPayload<K> } {
    return message.type === messageType;
}

如果sameType(message, messageType)返回true,则message将被缩小为已知payloadCorrespondingPayload<K>类型的类型.让我们使用它:

const someFn = <K extends Message['type']>(
    messageType: K,
    onMessage: (payload?: CorrespondingPayload<K>) => void
) => {
    const handleMessage = (message: Message) => {
        if (sameType(message, messageType)) {
            onMessage(message.payload); // okay
        }
    }
};

看上go 不错!

Playground link to code

Typescript相关问答推荐

ReturnType此索引方法与点表示法之间的差异

`((PrevState:NULL)=>;NULL)|null`是什么意思?

在MessageStore对象中实现条件类型时出现TypeScrip错误

泛型类型联合将参数转换为Never

打字类型保护递归判断

适当限制泛型函数中的记录

我可以以这样一种方式键入对象,只允许它的键作为它的值吗?

是否可以从函数类型中创建简化的类型,go 掉参数中任何看起来像回调的内容,而保留其余的内容?

如何实现异构数组内函数的类型缩小

如何将父属性类型判断传播到子属性

如何按属性或数字数组汇总对象数组

从route.参数获取值.订阅提供";无法读取未定义";的属性

如何从一个泛型类型推断多个类型

如何从对象或类动态生成类型

map 未显示控制台未显示任何错误@reaction-google-map/api

如何在Nextjs路由处理程序中指定响应正文的类型

有没有一种简单的方法可以访问Keyboard Shortcuts JSON文件中列出的每个命令的显示名称(标题)?

Typescript泛型-键入对象时保持推理

将函数签名合并到重载中

如何在故事书的Typescript 中编写decorator ?