求大佬,这样的情况typescript如何定义对象?

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

已知有一个对象,key和value对应

{
    a: { a1: 1 },
    b: { b9: 1 },
    c: { c5: 1 },
    d: { d2: 1 },
    ...
}

怎么用ts来定义这样的数组?

[{
    type: 'e',
    value: { e1: 1 }
}, {
    type: 'c',
    value: { c5: 1 }
}]
回复
1个回答
avatar
test
2024-06-29

研究了一下,这个问题可以分为两个部分

  1. 如何约束转化函数的入参类型

利用 template type 很方便可以解决:

type Src<Ks extends string> = {
    [K in Ks]: {
        [P in `${K}${number}`]: number
    }
}

const conv = <Ks extends string>(src: Src<Ks>) => {}
  1. 如何推导返回值类型:

我能想到的是 record 转 union 转 array,其中 UnionToArray 参考了网上的文章。

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
    ? I
    : never

type UnionToOvlds<U> = UnionToIntersection<
    U extends any ? (f: U) => void : never
>

type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never

type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true

type UnionToArray<T, A extends unknown[] = []> = IsUnion<T> extends true
    ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
    : [T, ...A]

type Src<Ks extends string> = {
    [K in Ks]: {
        [P in `${K}${number}`]: number
    }
}

const conv = <Ks extends string, T extends Src<Ks>>(src: T) => {
    const dist: { type: string, value: { [K: string]: number } }[] = []
    for (const k in src) {
        dist.push({ type: k, value: src[k] })
    }
    return dist as UnionToArray<{
        [K in keyof T]: {
            type: K
            value: T[K]
        }
    }[keyof T]>
}

const dist = conv(src)
//    ^?
//    const dist: [{
//        type: "a";
//        value: {
//            a1: number;
//        };
//    }, {
//        type: "b";
//        value: {
//            b9: number;
//        };
//    }, {
//        type: "c";
//        value: {
//            c5: number;
//        };
//    }, {
//        type: "d";
//        value: {
//            d2: number;
//        };
//    }]

遗憾的是这两个思路不能共存于一个函数(在我看来),你可以按需求选择入参约束或返回类型。

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