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

如何创建属性名由用户自定义的TypeScript interface接口?

问题解决方法

报错根本原因

TypeScript 类型系统完全在静态编译阶段执行,所有类型计算会在代码运行前完成,因此运行时定义的普通变量值不能直接放到类型声明位置使用,这是触发 ts(2749) 错误的核心原因。

第二个报错 Exported type alias 'renameProps' has or is using private name 'val' 是因为你定义的 renameProps 类型直接在内部引用了作用域内的局部变量 val 的类型,如果 val 未导出,导出 renameProps 时就会触发作用域校验错误。

正确实现方案

场景1:根据自定义属性名映射生成目标类型

对应你给出的示例需求,基于 userDefinedPropNames 映射生成目标接口的写法如下:

// 给配置对象加 as const 断言,保留内部字符串的字面量类型,否则会被推导为宽泛的string类型
const userDefinedPropNames = { xVal: 'somestring', yVal: 'anotherstring', group: 'athirdstring' } as const

interface PreData {
  xVal: number,
  yVal: number,
  group: string
}

// 先拿到配置对象的类型
type PropNameMap = typeof userDefinedPropNames
// 映射生成最终的Data类型
type Data = {
  [K in keyof PreData as PropNameMap[K]]: PreData[K]
}

此时生成的 Data 类型和你示例要求的完全一致:{ somestring: number; anotherstring: number; athirdstring: string }。

场景2:单个动态键的场景

对应你原来使用单个val作为键的需求,修改写法如下:

// 加as const保留字面量类型
const val = 'asdf' as const

// 用typeof val拿到值对应的类型,传入Record
type Data = Record<typeof val, number>

// 映射类型写法也需要把替换键做成泛型参数,避免内部引用外部变量导致作用域错误
type RenameProps<Type, NewKey extends string | number | symbol> = {
  [Property in keyof Type as NewKey]: Type[Property]
}
// 调用时传入typeof val作为泛型参数
type Data2 = RenameProps<PreData, typeof val>

额外注意事项

如果属性名是完全运行时才能拿到的动态值(比如后端接口返回、用户输入框输入),编译阶段无法拿到精确的字面量值,这种场景无法生成精确的固定类型,只能用Record<string, unknown>等宽泛类型标注,搭配运行时校验逻辑处理即可,因为TS类型会在编译后全部擦除,无法响应运行时的动态值变化。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:24:07