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

多级泛型类型转换不符合预期:递归包装值类型失败

问题分析与解决方案

问题根源

你写的TryToChangeType类型判断条件K extends { [Key2 in keyof K]: K[Key2] }本质上是恒成立的——任何类型(包括原始类型)都会通过这个检查,因为它只是把K的属性原样映射了一遍。这导致递归永远不会进入到包装原始类型的分支,所以changed变量的类型和实际赋值不匹配,引发报错。

修正后的类型定义

要实现递归遍历对象并包装原始类型的逻辑,需要先准确判断K是否是对象(且不是null)。TypeScript中可以用K extends object结合空值过滤,来区分对象类型和原始类型:

const obj = {
    _test1: 'hi',
    _test2: {
        test3: {
            _test4: {
                test5: 99,
            },
        },
    },
};

// 修正后的类型:递归遍历对象,包装原始类型
type TryToChangeType<K> = 
    K extends null ? { value: K } : // 单独处理null
    K extends object ? { [Key in keyof K]: TryToChangeType<K[Key]> } : 
    { value: K };

const changed: TryToChangeType<typeof obj> = {
    _test1: { value: 'hi' },
    _test2: {
        test3: {
            _test4: {
                test5: { value: 99 },
            },
        },
    },
}; // 现在不会报错了

扩展支持自定义包装结构

如果需要将原始类型包装成{value: 原类型, init: boolean}这类自定义结构,只需修改包装分支的返回值即可:

// 自定义包装类型
type WrappedValue<T> = {
    value: T;
    init: boolean;
};

type TryToChangeType<K> = 
    K extends null ? WrappedValue<K> :
    K extends object ? { [Key in keyof K]: TryToChangeType<K[Key]> } : 
    WrappedValue<K>;

// 使用示例
const changed: TryToChangeType<typeof obj> = {
    _test1: { value: 'hi', init: false },
    _test2: {
        test3: {
            _test4: {
                test5: { value: 99, init: true },
            },
        },
    },
};

保留原类型的访问

如果需要在代码中同时访问原类型和转换后的新类型,可以通过泛型参数直接引用:

// 直接通过typeof obj访问原类型
const original: typeof obj = obj;
// 通过转换类型访问新结构
const transformed: TryToChangeType<typeof obj> = changed;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 03:33:22