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

TypeScript对象转换时能否仅通过类型实现安全键缩小?

解决方案:通过类型定义实现A到B的安全转换(无需修改核心业务逻辑)

要在不改动reduce循环核心逻辑的前提下解决类型错误,同时保留类型校验能力,可以通过映射类型和条件类型建立A与B的强类型关联,再给函数参数添加精确的类型约束,让TypeScript正确推断类型匹配关系。

完整实现代码

enum Keys {
    Key1 = 'key1',
    Key2 = 'key2',
}

type A = {
    [Keys.Key1]?: {
        value: string;
    };
    [Keys.Key2]?: {
        value: number;
    };
};

// 工具类型:提取对象中value属性的类型
type ExtractValue<T> = T extends { value: infer V } ? V : never;

// 基于A自动生成B的类型,保证类型强关联
type B = {
    [K in keyof A]?: ExtractValue<A[K]>;
};

function func(obj: A): B {
    return Object.values(Keys).reduce(
        (prev, key: keyof A) => {
            if (key in obj) {
                // 非空断言:已通过key in obj确认属性存在
                // 精确类型断言:匹配当前key对应的B属性类型
                prev[key] = obj[key]!.value as B[typeof key];
            }
            return prev;
        },
        {} as B,
    );
}

方案说明

  1. 类型关联与校验

    • ExtractValue工具类型通过条件类型自动提取A中每个属性的value类型,确保B的类型完全依赖A定义。
    • 若手动修改B的类型与A不匹配(比如把B的Key1设为number),TypeScript会直接抛出类型错误,满足校验需求;若A中某属性的value变为number|null,B的对应属性会自动同步为number|null|undefined。
  2. 解决类型推断问题

    • 给循环中的key标注keyof A类型,让TypeScript明确它是A的合法键,而非宽泛的string类型。
    • obj[key]!的非空断言是安全的:已通过key in obj判断属性存在,无需担心undefined。
    • as B[typeof key]是精确的类型断言,针对当前key对应的B属性类型,避免了any的滥用,同时让TypeScript认可赋值操作。

额外验证:类型校验能力示例

如果修改A的类型,比如把Key2的value改为number|null:

type A = {
    [Keys.Key1]?: {
        value: string;
    };
    [Keys.Key2]?: {
        value: number | null;
    };
};

此时B的Key2会自动变为number | null | undefined,如果手动将B的Key2定义为number,TypeScript会报错:

// 报错:Type 'number | null | undefined' is not assignable to type 'number | undefined'
type B = {
    [Keys.Key1]?: string;
    [Keys.Key2]?: number;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 17:21:13