一种获取带有TypeScript

时间:2019-01-28 17:23:44

标签: typescript

说我有

interface A {
    b: {
         c: {
              d: string;
              e: number;
         }
    }
}

我想获得与A_no_E相同的界面A,但没有A.b.c.e

interface A_no_E {
    b: {
         c: {
              d: string;
         }
    }
}

是否可以通过高级类型的TypeScript 便捷地获取A_no_E,而不必逐个重新声明整个内容

2 个答案:

答案 0 :(得分:2)

嗯,我想您可以声明自己的DeepOmit mappedconditional类型的函数,该函数遍历键的元组……类似这样:

// Tail removes the first element from a tuple type
// so Tail<[string, number, boolean]> is [number, boolean]
type Tail<L extends any[]> =
  ((...l: L) => void) extends ((h: infer H, ...t: infer T) => void) ? T : never;


type DeepOmit<T, K extends Array<keyof any>> =
  K extends [] ? T : K extends [infer P] ? Pick<T, Exclude<keyof T, P>> : {
    [P in keyof T]: P extends K[0] ? DeepOmit<T[P], Tail<K>> : T[P]
  }

然后您可以做

type A_no_E = DeepOmit<A, ['b', 'c', 'e']>;

如果您使用IntelliSense,则评估结果看起来有点难看

type A_no_E = {
    b: {
        c: Pick<{
            d: string;
            e: number;
        }, "d">;
    };
}

与您想要的等同:

declare const a_no_e: A_no_E
a_no_e.b.c.d; // string
a_no_e.b.c.e; // error, property e does not exist

编辑:DeepOmit的替代定义产生了较不难看的IntelliSense:

type Tail<L extends any[]> =
  ((...l: L) => void) extends ((h: infer H, ...t: infer T) => void) ? T : never;
type DeepOmit<T, K extends Array<keyof any>, KT extends keyof T = Exclude<keyof T, K[0]>> =
  K extends [] ? T : K extends [infer P] ? { [Q in KT]: T[Q] } : {
    [P in keyof T]: P extends K[0] ? DeepOmit<T[P], Tail<K>> : T[P]
  }

现在A_no_E在IntelliSense中显示为:

type A_no_E = {
    b: {
        c: {
            d: string;
        };
    };
}

希望有帮助。

答案 1 :(得分:0)

如果您确切地知道要忽略的路径,我想您可以使用像example这样的交集类型来做到这一点。想法是将不接受指定路径上的值的类型与原始类型A相交。