说我有
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
,而不必逐个重新声明整个内容?
答案 0 :(得分:2)
嗯,我想您可以声明自己的DeepOmit
mapped和conditional类型的函数,该函数遍历键的元组……类似这样:
// 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
相交。