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

TypeScript:通过对象字面量映射重命名类型字段(支持嵌套)

问题与解决方案

问题背景

现有Person接口定义如下:

interface Person {
    id: string;
    name: string;
    dob: Date;
    dod?: Date;
    nicknames?: string[];
    age: number;
    height: number;
    weight: number;
}

需要实现泛型函数getThing,接收目标类型(如Person)和字段映射对象(支持重命名),返回对应新类型。示例调用后,返回值类型需符合预期:

const a = getThing<Person>({
    id: "id" as const,
    name: "name" as const,
    dateOfBirth: "dob" as const,
});
// 期望a的类型:{ id: string; name: string; dateOfBirth: Date; }

尝试的代码出现R[k] cannot be used to index T错误,同时希望扩展支持嵌套字段重命名(如将Person.contact.homePhone重命名为ice.phone),用于构建类型化GraphQL查询工具。


一、解决基础字段重命名的类型错误

原代码的核心问题是对泛型R的约束不足,TypeScript无法确认R[k]必然是T的键。只需给R添加明确约束即可修复:

function getThing<T, R extends Record<keyof R, keyof T>>(
    fields: R
): { [K in keyof R]: T[R[K]] } {
    // 业务逻辑实现,此处用类型断言占位
    return {} as any;
}

优化调用体验(TS 4.5+)

如果升级到TypeScript 4.5及以上版本,可利用自动字面量类型推断,无需手动添加as const:

const a = getThing<Person>({
    id: "id",
    name: "name",
    dateOfBirth: "dob",
});
// 自动推断a的类型为 { id: string; name: string; dateOfBirth: Date; }

二、扩展支持嵌套字段重命名

要实现嵌套字段的映射,需要定义递归类型来处理层级结构:

1. 定义辅助类型

首先定义描述嵌套映射结构的类型,以及递归解析的返回类型:

// 描述支持嵌套的字段映射规则
type FieldMapping<T> = {
    [K: string]: keyof T | FieldMapping<T[keyof T]>;
};

// 递归生成最终的返回类型
type MappedResult<T, M extends FieldMapping<T>> = {
    [K in keyof M]: 
        M[K] extends keyof T ? T[M[K]] :
        M[K] extends FieldMapping<infer U> ? MappedResult<U, M[K]> :
        never;
};

2. 修改泛型函数

更新getThing的类型约束,适配嵌套场景:

function getThing<T, M extends FieldMapping<T>>(
    fields: M
): MappedResult<T, M> {
    // 嵌套字段的实现需递归遍历映射对象,此处用类型断言占位
    return {} as any;
}

3. 嵌套场景使用示例

先扩展Person接口添加嵌套字段:

interface ContactInfo {
    homePhone: string;
    email: string;
}

interface Person {
    id: string;
    name: string;
    dob: Date;
    dod?: Date;
    nicknames?: string[];
    age: number;
    height: number;
    weight: number;
    contact: ContactInfo;
}

调用getThing传入嵌套映射:

const b = getThing<Person>({
    id: "id",
    name: "name",
    dateOfBirth: "dob",
    ice: {
        phone: "homePhone"
    }
});

此时b的类型自动推断为:

{
    id: string;
    name: string;
    dateOfBirth: Date;
    ice: { phone: string };
}

版本要求

嵌套方案依赖TypeScript 4.1+的递归条件类型支持,当前使用的4.3.5版本完全兼容,无需升级。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 22:55:18