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

如何从给定TypeScript对象动态生成指定结构的类型?

问题描述

给定以下TypeScript对象:

const myObject = {
   AdminInviteStudent:  ['inviterGivenName', 'inviterFamilyName', 'link'],
   DeleteMappingStudent: ['teacherGivenNameAndInitialOfFamilyName', 'studentGivenName', 'noteLink']
};

需要编写一个工具类型GetType,实现如下用法:

export type EmailTemplateParameters = GetType<typeof myObject>;

最终生成的类型结构需将数组中每个值设为必填的string类型,如下:

{
  AdminInviteStudent: {
    inviterGivenName: string;
    inviterFamilyName: string;
    link: string;
  };
  DeleteMappingStudent: {
    teacherGivenNameAndInitialOfFamilyName: string;
    studentGivenName: string;
    noteLink: string;
  };
}

同时需要优化原问题:如何将TypeScript类型导出为对象以暴露可用的键。

解决方案

1. 修正对象定义(保留字面量类型)

首先要让TypeScript保留数组元素的字面量类型,需给对象添加as const断言——否则TS会将数组推断为string[],无法获取具体的键名:

const myObject = {
  AdminInviteStudent: ['inviterGivenName', 'inviterFamilyName', 'link'],
  DeleteMappingStudent: ['teacherGivenNameAndInitialOfFamilyName', 'studentGivenName', 'noteLink']
} as const;

2. 编写工具类型GetType

通过映射类型实现需求:遍历对象的每个键,再遍历对应数组的每个元素,生成必填的string属性:

type GetType<T extends Record<string, readonly string[]>> = {
  [K in keyof T]: {
    [P in T[K][number]]: string;
  };
};

3. 生成目标类型

直接使用工具类型即可得到所需结构:

export type EmailTemplateParameters = GetType<typeof myObject>;
原问题优化方案

原问题核心是让类型与运行时对象共享单一数据源,避免重复定义导致不一致,推荐以下优化:

  • 强制单一数据源:用as const或封装函数确保运行时对象和类型同步,比如封装一个模板定义函数:

    function defineTemplates<T extends Record<string, readonly string[]>>(templates: T) {
      return templates;
    }
    
    const myTemplates = defineTemplates({
      AdminInviteStudent: ['inviterGivenName', 'inviterFamilyName', 'link'],
      DeleteMappingStudent: ['teacherGivenNameAndInitialOfFamilyName', 'studentGivenName', 'noteLink']
    } as const);
    

    这样既能约束输入,又能自动推导类型,避免遗漏as const。

  • 运行时获取键列表:如果需要在运行时获取可用的模板名称,可编写工具函数:

    function getTemplateKeys() {
      return Object.keys(myObject) as Array<keyof typeof myObject>;
    }
    

    确保运行时获取的键与类型完全匹配,不会出现类型不兼容问题。

  • 扩展灵活性:如果后续需要支持非string类型的参数,可将数组改为对象结构,比如:

    const myObject = {
      AdminInviteStudent: [
        { key: 'inviterGivenName', type: 'string' as const },
        { key: 'expireDays', type: 'number' as const }
      ]
    } as const;
    

    再修改工具类型推导对应类型,满足更复杂的参数类型需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:26:27