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

TypeScript中如何让switch语句自动推断props类型?

解决方案:TypeScript中switch分支自动推断props类型

问题场景

我编写了包含多个interface、组件及PropsMap的TypeScript代码,在MyFunc函数的switch语句中,希望TypeScript能根据传入的key自动推断props的对应类型,无需手动写类型断言。试过泛型映射方案但未成功,目前给每个key创建类型守卫能实现需求,但过于繁琐,想找更简洁的解决办法。

原始代码

interface FooProps {
    'keyInFoo': string
}
const Foo = (props: FooProps) => {}

interface BarProps {
    'keyInBar': string
}
const Bar = (props: BarProps) => {}

interface PropsMap {
    'foo': FooProps,
    'bar': BarProps,
    //.. baz, etc...
}
type keyName = keyof PropsMap

const MyFunc = <T extends keyName>(key: T)  => {
    const props: PropsMap[T] = getProps(key)

    switch(key) {
        // 理论上T为'foo'时,props应该是FooProps
        case 'foo': return Foo(props) // <- 错误:类型'BarProps'中缺少属性'keyInFoo'
        case 'bar': return Bar(props) // <- 错误:类型'FooProps'中缺少属性'keyInBar'
    }
}

const getProps = <T extends keyName>(key: T): PropsMap[T] => {
    // ... 获取props的业务逻辑
    return {} as PropsMap[T]
}

试过的方案

泛型映射类型(无效)

尝试用条件泛型做类型映射,但没有达到预期效果:

type PropsGeneric<T extends keyName> = 
    T extends 'foo' ? FooProps :
    T extends 'bar' ? BarProps : never;

类型守卫方案(可行但繁琐)

给每个key单独写类型守卫,再用if-else if语句判断:

const isFoo = <T extends keyName>(key: T, props: PropsMap[T]): props is FooProps => key === 'foo'
const isBar = <T extends keyName>(key: T, props: PropsMap[T]): props is BarProps => key === 'bar'

// ... 更多key对应的类型守卫

简洁解决方案

核心思路是让TypeScript建立key和props的类型关联,利用字面量类型收窄特性,让switch/if分支自动识别对应类型。

方案1:直接用if分支收窄类型

不需要额外定义类型守卫,直接通过判断key的字面量值,TypeScript会自动收窄props的类型:

const MyFunc = <T extends keyName>(key: T) => {
    const props = getProps(key);

    if (key === 'foo') {
        // 自动推断props为FooProps
        return Foo(props);
    } else if (key === 'bar') {
        // 自动推断props为BarProps
        return Bar(props);
    }
}

方案2:用联合类型元组关联key与props

如果偏好使用switch语句,可以通过构造联合类型元组,让TypeScript同时收窄key和props的类型:

// 先定义组件与key的映射(可选,用于统一管理)
const ComponentMap = {
    foo: Foo,
    bar: Bar,
    // ... 其他组件
} as const;

// 生成联合类型,关联key、组件、props的对应关系
type ComponentEntry = {
    [K in keyof typeof ComponentMap]: [K, typeof ComponentMap[K], PropsMap[K]]
}[keyof typeof ComponentMap];

const MyFunc = <T extends keyName>(key: T) => {
    const props = getProps(key);
    // 构造元组,让TypeScript建立key与props的类型关联
    const entry = [key, ComponentMap[key], props] as ComponentEntry;

    switch(entry[0]) {
        case 'foo':
            // 自动推断entry[2]为FooProps
            return entry[1](entry[2]);
        case 'bar':
            // 自动推断entry[2]为BarProps
            return entry[1](entry[2]);
    }
}

原理说明

TypeScript的类型收窄依赖值的字面量判断:当你在if/switch分支中明确判断key是某个具体字面量时,TypeScript会自动将泛型T收窄为该字面量类型,进而PropsMap[T]也会被同步收窄为对应的props类型,无需手动断言。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:40:42