递归转换嵌套对象类型以修改所有值类型

时间:2020-10-06 17:34:03

标签: javascript typescript

我希望能够转换一个任意的接口定义,以使层次结构和键保持完整,但是将所有值类型更改为一个新的值。

示例

源对象:

export interface MyObject {
  id: string
  created: Date
  deleted?: boolean
  data: {
    history: string[]
  }
  meta?: {
    aggregation: {
      min: number
      max: number
    }
  }
}

目标对象将所有非记录类型替换为string

export interface MyObject {
  id: string
  created: string
  deleted?: string
  data: {
    history: string
  }
  meta?: {
    aggregation: {
      min: string
      max: string
    }
  }
}

我尝试过的

type ConvertToStringValue<T> = {
  [K in keyof T]: T[K] extends Record<string, unknown> ? Record<K, ConvertToStringValue<T[K]>> : string
}
let convertedMyObject: ConvertToStringValue<MyObject>

我的推理:

  • 对于每个键,我们检查该值是否为Record。
  • 如果是,我们定义一个Record并递归计算该值
  • 如果没有,则该值必须为字符串

虽然不起作用。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您很亲密,只是不要将转换后的值包装到另一个记录中。直接返回:

type ConvertToStringValue<T> = {
  [K in keyof T]: T[K] extends Record<string, unknown> | undefined ? ConvertToStringValue<T[K]> : string
}

这似乎可以提供您想要的推断:

declare let convertedMyObject: ConvertToStringValue<MyObject>;
convertedMyObject.id // string
convertedMyObject.created // string
convertedMyObject.deleted // string | undefined
convertedMyObject.data.history // string
convertedMyObject.data.min // string
convertedMyObject.meta.aggregation.min // Error: Object is possibly undefined
convertedMyObject.meta?.aggregation.min // string | undefined