TypeScript 推导嵌套对象类型的字符串路径

返回
Author Avatar
钢翼
2024-04-28
编程
40

参考 https://ououe.com/posts/typescript-object-deep-path

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAchDOwIBMAKBDYALAPAFSggA8kA7ZeKAcnQCdb0QqoAfagewCMArCAY2BUANFFQiAwlAC8UAK7kIAMwCWpFAD5pUAAYASAN6ooAMiiJaqgOYBfAwWJkK1OgyZQA-DoDaB0rIC2nBC01gC62lAAXNRUtvqSDhDklOZWHjoAdAbi1hHRVLHaALAAUKWgkFAAIhAQYHCIKDgAaiIA0loFmjLNhCRJTly8Al6hpVDpDUhomLg09IzCUG0iNXUY2C1efoHBoZps8shKqhrjUVC9iclypADWpOwA7qSj555TKBtzLovt6udold+jchvxgO9YAhpt8cFQwQIlitqrUwLDmuoASUJtE1AA3YKlcrgaBrNGzfB9RyUBHAbpQfTnLwARSgqigdwgIHYiigeFCAFp3NFWWwyZ9kDgYOxSDBZAAbeXoTjyiD4Fn7ETMrHWLyc7m8-lEsolCrQACCWjJsMZ2LZyGiqVIlnOpHQ-ggjuAFmdpWsmgA9AHqMpkMw2FQ3R6qMazVAAEJW1E286hr0+l121SKdjRW0TCZRz1mb1Wc4TMBYGXFp2ZibWP2B4NUUPhkOkHNtlsd9gZItd7O9yvVmMmuOSGTWin5+3pst2vhYZTy5C0JLRc0LEA4GeF9010u+u0VqtqOdH+s6pshsOsaiL5erpJt7QPldr16+AJBELhO+vpd3ySHx9B2H8wj7fcIjYADHw-ECwOCCDhzUYoxxJaok3WadzmQTADwzc5ZHgYI83LKAi3POsC3QZAn3geAqPOXUxhKf0oCDKABU0AAiPCkB4u8eOI4JBJgkTaAQ78kL-cSSMkr9dl-SCPWgnQJKkpSINo+j4DQ4lKgAUSw8lNhnNMS0IrMezI48KP3Ji7JQgj5wLKA3yfUgNy3HdyL3D1HLck9q0Cgt-WYoj5NstzKMs1yaLotcGNChs2OvFtbwjQcBx7FSIBynMMmcrsJIK3sPI-F9BwyCrgMU8DZJ0aras-UDpOUos1O0ZrAM8zSGqK08IDUqgJLykr5IyHSkvgUcDOgAAxEyUztdA8ygTh1r4daHQZFznSgawjtS9jOJoLt0AyTgLqumqbs4GqMky5xbr4J6Mny2MMIAcWWnDVvWzaGXcna832yxDsO0ZIZYxsOObdAX3QfqZK65H6pkq60ZR5SHr4bGMdxmqcbCAm2q00JXpJynkDJxCib4an3uG0ogA

type E = DeepPath<{
  id: string
  info: {
    name: string
    phone: string
    children: Array<{
      name: string
      phone: string
    }>
  }
  user: {
    name: string
    address: string
  }
}> // 'id' | 'info' | 'info.name' | 'info.phone' | 'user' | 'info.children' | `info.children[${number}]` | `info.children[${number}].name` | `info.children[${number}].phone` | 'user.name' | 'user.address'

配合lodash的 .get和.set使用,封装高阶组件简直不要太爽。

注意:上述代码如果在处理嵌套自身类型的时候会报错。需参考 https://www.saoniuhuo.com/question/detail-2463280.html 限制最大层级,避免报错

type NestedKeyOf<T extends object, D extends any[] = [0, 0, 0, 0, 0, 0, 0, 0]> =
    D extends [any, ...infer DD] ? ({
        [K in keyof T & (string | number)]: T[K] extends object
        ? `${K}` | `${K}.${NestedKeyOf<T[K], DD>}`
        : `${K}`
    }[keyof T & (string | number)]) : never;

代码虽然不一样,但是思想是一样的,通过数组长度每次-1处理