Typescript 中如何编写含复杂返回值的函数类型声明?

作者站长头像
站长
· 阅读数 13

实现了一个函数可实现对象扁平化,数据转换示例(传入 => 传出):

{ margin: { left: '20px', right: '30px' } } => { 'margin-left': '20px', 'margin-right': '30px' }
{ color: { button: { warning: 'yellow' } } } => { 'color-button-warning': 'yellow' }

请问如何编写函数的类型声明呢?以便于vscode里面提示扁平化后自动生成的键名,对开发者友好,比如 color-button-warning 和 margin-left。

补充一下传入的结构化数据的类型声明:declare const a = {margin: {left: string}}

类似这样,是自动生成的。

回复
1个回答
avatar
test
2024-07-17

做个类型体操就行,大致写了下,

type JoinKey<P extends string, K extends string>
  = P extends '' ? K : `${P}-${K}`

type Inner<T, P extends string = ''> =
  {
    [K in keyof T]:
    T[K] extends object
    ? Inner<T[K], JoinKey<P, K & string>>
    : [JoinKey<P, K & string>, T[K]]
  }[keyof T]

type _Flat<T>
  = T extends [string, string | number | boolean]
  ? {
    [K in T[0]]: T[1]
  }
  : T extends [string, object]
  ? _Flat<T[1]>
  : never

type UnionToIntersection<T> =
  (T extends any ? (x: T) => any : never) extends
  (x: infer R) => any ? R : never

type FlatObject<T> = UnionToIntersection<_Flat<Inner<T>>>


declare function flatObj<T>(obj: T): FlatObject<T>

const res = flatObj({
  margin: {
    left: '10px',
    right: '8px',
  },
  padding: {
    top: '4px'
  },
  color: {
    button: {
      success: 'green',
      failure: {
        active: 'red',
        hover: 'pink'
      }
    }
  } 
}) 

answer image

PS: 应该是有更好的写法,不过暂时也没想好。另外有个问题这里没有推断出对应的值出来

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容