typescript 从合并的类型生成具有共享属性名称的类型时,为什么合并具有该属性名称的两个类型不起作用?

xwbd5t1u  于 2023-03-04  发布在  TypeScript
关注(0)|答案(1)|浏览(110)
type a = {
    a: number
    b: {d: string}[]
}
type b = {
    c : string
    b: {f: number}[]
}

type l = a & b

const ab: l = {a: 1, c: '', b: [{d: '', f:1}]}

const ac: l['b'] = [{ d: '', f: 1}]

Playground
在将类型ab合并为类型l之后,为什么类型lconst ab工作,而类型l['b']const ac不工作?
我尝试在vscode上编写此代码,但在const ac上出现此错误:

Type '{ d: string; f: number; }[]' is not assignable to type '{ d: string; }[] & { f: number; }[]'.
  Types of property 'pop' are incompatible.
    Type '() => { d: string; f: number; }' is not assignable to type '(() => { d: string; }) & (() => { f: number; })'.
      Type '() => { d: string; f: number; }' is not assignable to type '() => { d: string; }'.
        Type '{ d: string; f: number; }' is not assignable to type '{ d: string; }'.
          Object literal may only specify known properties, and 'f' does not exist in type '{ d: string; }'.

为什么类型l['b']不包含来自类型{ d: string; }[] & { f: number; }[]的合并类型{d: string, f: number}[],而它包含类型l

e4eetjau

e4eetjau1#

这是TypeScript中的一个已知错误,在microsoft/TypeScript#42715中报告。显然,类型为intersectedarray类型的对象属性错误地接收到多余的属性警告。在microsoft/TypeScript#43707中曾尝试修复它,但它显然在现实世界的代码库中造成了不希望的错误,因此根据此注解恢复了它。看起来它不会很快得到修复。
请注意,交叉数组会以其他不希望的方式运行,例如microsoft/TypeScript#41874,因此最好尽可能避免此类类型;你可以编写自己的实用程序类型来执行递归的类似于交集的操作,这种操作在数组中表现得更好。例如:

type IntersectNestedArrays<T, U> =
    (T extends readonly any[] ? U extends readonly any[] ?
        { [I in keyof T]: MapInt<T[I], U[Extract<I, keyof U>]> } :
        MapInt<T, U> : MapInt<T, U>)

type MapInt<T, U> = ({
    [K in keyof (T & U)]:
    K extends keyof T ? K extends keyof U ?
    IntersectNestedArrays<T[K], U[K]> : T[K] :
    K extends keyof U ? U[K] : never
}) extends infer O ? { [K in keyof O]: O[K] } : never;

type L = IntersectNestedArrays<A, B>;
/* type L = {
    a: number;
    b: {
        d: string;
        f: number;
    }[];
    c: string;
} */

详细讨论该类型如何工作可能超出了问题的范围,但关键是,结果类型包含您实际需要的{d: string, f: number}[]类型,然后您完全避免了遇到的bug:

const ab: L =
    { a: 1, c: '', b: [{ d: '', f: 1 }] }; // okay

Playground代码链接

相关问题