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

TypeScript中使用switch语句实现泛型类型推断的方法

问题描述

我正尝试创建一个带有不同配置的泛型类型,这些配置是不同实现之间的唯一差异。以下是我的代码示例:

interface Generic<Config extends ConfigurationType> {
    configuration_type: Config
    configuration: TypeToConfigMap[Config]
}

class ConfigA { z = 1 } // empty classes make bad examples
class ConfigB { y = 2 }
class ConfigC { x = 3 }

const enum ConfigurationType {
    a = 'a',
    b = 'b',
    c = 'c',
}

interface TypeToConfigMap {
    [ConfigurationType.a]: ConfigA,
    [ConfigurationType.b]: ConfigB,
    [ConfigurationType.c]: ConfigC,
}

核心问题出在下面的函数中:

function test(generic: Generic<ConfigurationType>[]) {
    generic.forEach((generic) => {
        switch (generic.configuration_type) {
            case (ConfigurationType.a):
                generic.configuration.z; // 无法推断z属性
                break;
            case (ConfigurationType.b):
                generic.configuration.y; // 无法推断y属性
                break;
            case (ConfigurationType.c):
                generic.configuration.x; // 无法推断x属性
                break;
        }
    })
}

switch语句中generic.configuration的类型无法被正确推断,我希望保持这种简洁写法,请问有没有办法让类型得到正确推断?

解决方法

问题根源在于Generic<ConfigurationType>会被TypeScript解析为泛型实例的合并类型,而非能触发自动类型窄化的判别联合类型。要实现switch中的类型推断,只需调整类型定义:

方案一:使用判别联合类型(推荐)

先定义包含所有可能情况的联合类型,再让函数接收该类型的数组:

// 生成包含所有配置实例的联合类型
type GenericInstance = {
    [K in ConfigurationType]: Generic<K>
}[ConfigurationType]

// 修改函数参数类型为联合类型数组
function test(generic: GenericInstance[]) {
    generic.forEach((item) => {
        switch (item.configuration_type) {
            case ConfigurationType.a:
                item.configuration.z; // 自动推断为ConfigA,z属性可用
                break;
            case ConfigurationType.b:
                item.configuration.y; // 自动推断为ConfigB
                break;
            case ConfigurationType.c:
                item.configuration.x; // 自动推断为ConfigC
                break;
        }
    })
}

原理

{[K in ConfigurationType]: Generic<K>}[ConfigurationType]会遍历枚举的每个值,生成对应的Generic<K>类型,最终合并为Generic<'a'> | Generic<'b'> | Generic<'c'>。TypeScript识别到这是带有明确判别字段(configuration_type)的联合类型后,会在switch匹配时自动窄化对应成员的类型。

方案二:泛型函数+类型断言

如果不想额外定义联合类型,也可以用泛型函数配合手动断言,但这种方式不够优雅:

function test<T extends ConfigurationType>(generic: Generic<T>[]) {
    generic.forEach((item) => {
        switch (item.configuration_type) {
            case ConfigurationType.a:
                (item.configuration as ConfigA).z;
                break;
            case ConfigurationType.b:
                (item.configuration as ConfigB).y;
                break;
            case ConfigurationType.c:
                (item.configuration as ConfigC).x;
                break;
        }
    })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 09:24:58