【问题标题】:What is the correct type for splitting an object in two complimentary objects in Typescript?在 Typescript 中将一个对象拆分为两个免费对象的正确类型是什么?
【发布时间】:2023-02-03 16:37:11
【问题描述】:

将对象拆分为两个子对象的正确 Typescript 类型是什么,每个子对象都包含互补键,例如,表单的对象

{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: string; }' is not assignable to type 'A'”和“'{ x: string; }' is assignable to the constraint of type 'A'”。

【问题讨论】:

  • 错误消息说A extends Partial&lt;Union&gt;可以是{ x: string },但也可以是{ y: number }。或者{ x: string; y: number}。对于A的不同值,您得到Split&lt;SpecificUnion&gt;的不同定义,但是Split&lt;Union&gt;没有被A参数化,因此它不应该依赖于A的定义。
  • "y" 不是数字。

标签: typescript


【解决方案1】:

错误信息说A extends Partial&lt;Union&gt;可以是{ x: string },但也可以是{ y: number }。或者{ x: string; y: number }。

对于A的不同值,您会得到Split&lt;SpecificUnion&gt;的不同定义,但是Split&lt;Union&gt;没有被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" },
    }
}

检查它online。

【讨论】:

  • 谢谢@axiac,最后一句话是什么意思?似乎 split3 只是未类型化。编译器如何推断它是否真的是某个联合的拆分实例?
  • 哎呀,你是对的。我不知道我在写那部分的时候在想什么。我从答案中删除了它。
猜你喜欢
  • 2014-10-03
  • 2017-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-20
  • 2019-04-23
  • 1970-01-01
  • 2016-02-11
相关资源
最近更新 更多