You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript双重泛型问题:Listener类型为何提示‘非泛型’错误

TypeScript泛型函数类型报错:Type 'Listener' is not generic

先看报错的代码:

type ListenerShape<
  EventType extends string,
  EventTypeMapData extends {
    [key in EventType]: unknown;
  }
> = <E extends EventType>(data: EventTypeMapData[E]) => void;

enum EventType {
    A = 'a',
    B = 'b',
}

type EventTypeMapData = {
    [EventType.A]: number,
    [EventType.B]: string,
}

type Listener = ListenerShape<EventType, EventTypeMapData>;
type AListener = Listener<EventType.A>; // 此处报错:Type 'Listener' is not generic

问题原因

ListenerShape是一个泛型类型,它接受EventType和EventTypeMapData两个参数后,返回的是一个泛型函数类型。但当你把ListenerShape<EventType, EventTypeMapData>赋值给Listener时,TypeScript会直接解析出这个泛型函数的具体类型——此时Listener已经是一个确定的函数类型(不再是泛型函数类型),自然无法再传入EventType.A这样的泛型参数。

解决方案

根据需求不同,有两种常见的处理方式:

方式一:调整泛型参数层级,把事件类型作为外层泛型参数

如果需要给特定事件类型定义监听器,可以把E(具体事件类型)提升为ListenerShape的外层泛型参数:

type ListenerShape<
  EventType extends string,
  EventTypeMapData extends { [key in EventType]: unknown },
  E extends EventType
> = (data: EventTypeMapData[E]) => void;

enum EventType {
    A = 'a',
    B = 'b',
}

type EventTypeMapData = {
    [EventType.A]: number,
    [EventType.B]: string,
}

// 直接传入具体事件类型来定义监听器
type AListener = ListenerShape<EventType, EventTypeMapData, EventType.A>;

方式二:直接使用泛型函数类型,跳过中间的Listener定义

如果需要保留原有的泛型函数结构,不需要先定义Listener,直接针对特定事件类型推导:

type ListenerShape<
  EventType extends string,
  EventTypeMapData extends { [key in EventType]: unknown }
> = <E extends EventType>(data: EventTypeMapData[E]) => void;

enum EventType {
    A = 'a',
    B = 'b',
}

type EventTypeMapData = {
    [EventType.A]: number,
    [EventType.B]: string,
}

// 直接定义对应事件A的监听器类型
type AListener = (data: EventTypeMapData[EventType.A]) => void;

内容的提问来源于stack exchange,提问作者Mebtte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:46:32