防止两种类型在TypeScript

时间:2019-07-09 21:18:50

标签: typescript

我在Array.ts中有以下声明,它们充当Array<T>.flat()Array<T>.flatDeep()的帮助程序类型和声明。

export {}

type ElementType<T> = T extends (infer U)[] ? U : T;
type JaggedArrayItem<T> = T | JaggedArray<T>;
type JaggedElementType<T> = T extends JaggedArray<infer U> ? U : T;
interface JaggedArray<T> extends Array<JaggedArrayItem<T>> { }

declare global {
    interface Array<T> {
        /**
         * Flattens the array one level, removing empty elements.  Does not flatten recursively.
         *
         * @example
         * [1, [2, 3]].flat() // => [1, 2, 3]
         *
         * @example
         * [[1, [2, 3], [4, [5]]], 6].flat() // => [1, 2, 3, 4, [5], 6]
         *
         * @example
         * let arr = new Array(3);
         * arr[0] = 1;
         * arr[2] = undefined;
         *
         * arr.flat() // => [1, undefined]
         */
        flat(): ElementType<T>[];

        /**
         * Flattens the array recursively.  Removes empty elements.
         *
         * @example
         * [1, [2, 3]].flatDeep() // => [1, 2, 3]
         *
         * @example
         * [[1, [2, 3], [4, [5]]], 6].flatDeep() // => [1, 2, 3, 4, 5, 6]
         *
         * @example
         * let arr = new Array(3);
         * arr[0] = 1;
         * arr[2] = undefined;
         *
         * arr.flatDeep() // => [1, undefined]
         */
        flatDeep(this: JaggedArray<T>): JaggedElementType<T>[];
    }
}

Array<T>.flat()仅展平阵列的一个深度,而Array<T>.flatDeep()展平整个物体。

[1, [2, [3]]].flat() // => [1, 2, [3]]
[1, [2, [3]]].flatDeep() // => [1, 2, 3]

但是,当我对此进行编译时,有时会出现错误:

  

返回类型注释会循环引用自身。

奇怪的是,我有时只会得到这个。有时它编译良好。但是,即使编译正常,此错误也会出现在生成的Array.d.ts文件中。

如果我只声明ElementType<T>JaggedElementType<T>中的一个,则相应的函数可以很好地编译,但是显然另一个函数则不能。

问题在于JaggedElementTypeElementType的超集。

如何防止它们重叠?

1 个答案:

答案 0 :(得分:0)

经过几个小时的整理(并且在我要单击该问题的发布按钮之前,正确),我发现了这一点,所以我想写自己的答案。

诀窍是,在ElementType<T>中检测T是否扩展了JaggedArray<T>,如果是,则它不是ElementType。我们通过使用never关键字来做到这一点。

type ElementType<T> = 
    T extends JaggedArray<T> ? never : 
    T extends Array<infer U> ? U : 
    T;