在Typescript中,将一个对象拆分为两个互补对象的正确类型是什么?

pxq42qpu  于 2023-02-05  发布在  TypeScript
关注(0)|答案(1)|浏览(130)

将一个对象拆分为两个子对象(每个子对象包含补充键)的正确类型是什么,例如,以下形式的对象

{x: "x", y: "y", z:"z"}

应该被分割成一个对象

{ a: {x: "x"}, b: {y: "y", z:"z"}}.

常规记录的此对象类型是什么?
我已经试过了,但是它给了我一个错误:

type Split<Union extends Record<string, string | number>>= <A extends Partial<Union>>() => {
    a: A,
    b: Omit<Union, keyof A>
};

type SpecificUnion = {
    x: string
    y: number
    z: string
}

const split: Split<SpecificUnion> = () => {
    return {
        a: { x: "x" },
        b: { y: "y", z: "z"}
}}

我得到了错误

Type '() => { a: { x: string; }; b: { y: string; z: string; }; }' is not assignable to type 'Split<SpecificUnion>'.
  Call signature return types '{ a: { x: string; }; b: { y: string; z: string; }; }' and '{ a: A; b: Omit<SpecificUnion, keyof A>; }' are incompatible.
    The types of 'a' are incompatible between these types.
      Type '{ x: string; }' is not assignable to type 'A'.
        '{ x: string; }' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype of constraint 'Partial<SpecificUnion>'.

这个错误似乎自相矛盾,因为它说“'{x:字符串; }"不能赋值给类型“A”“和”{x:string; }“可赋给类型为”A“的约束”。

owfi6suc

owfi6suc1#

错误消息指出A extends Partial<Union>可以是{ x: string },但也可以是{ y: number }{ x: string; y: number }
对于A的不同值,您会得到Split<SpecificUnion>的不同定义,但Split<Union>未被A参数化,因此它不应依赖于A的定义。
解决方法是将A设为Split类型的参数:

type Split<Union extends Record<string, string | number>, A extends Partial<Union>> = () => {
    a: A,
    b: Omit<Union, keyof A>
};

type SpecificUnion = {
    x: string
    y: number
    z: string
}

const split1: Split<SpecificUnion, { x: string }> = () => {
    return {
        a: { x: "x" },
        b: { y: 3, z: "z" },
    }
}

const split2: Split<SpecificUnion, { x: string, y: number }> = () => {
    return {
        a: { x: "x", y: 3 },
        b: { z: "z" },
    }
}

上网查一下。

相关问题