我正在尝试寻找一种方法来省略接口中n
数目的父属性和嵌套属性。在下面的例子中,我正在尝试省略一个父属性和两个嵌套属性。Omit
类型只能达到一个级别的深度。我能够find something close,但它仍然不起作用:
interface IFirstObject {
id: string;
revisionId: string;
someProperty: ISecondObject;
}
interface ISecondObject {
somePropertyToKeep: string;
firstPropertyToOmit: string;
secondPropertyToOmit: string;
}
/// How can we create a type to behave like the below result I am looking for?
type SomeNestedOmitType<TEntity, TOmissions> = {...}
// Desired Result
const myObject: SomeNestedOmitType<IFirstObject, "id" | "someProperty.firstPropertyToOmit" | "someProperty.secondPropertyToOmit"> = {
revisionId: "some revision id",
someProperty: {
somePropertyToKeep: "some property to keep"
}
}
TypeScript中有没有办法做到这一点?
使用TypeScript 5
1条答案
按热度按时间wwwo4jvm1#
我下面给出的解决方案可以按照问题中的示例代码的预期工作。可能的未来读者应该注意:根据我的经验,这种深度嵌套的类型Map往往会有奇怪的边缘情况,如果不能接受,有时可能需要完全重构来解决。
下面是
NestedOmit<T, K>
的一个可能实现:这使用键重Map来抑制直接出现在
K
中的T
的任何键;这部分只是“正常”Omit
的替代品,如microsoft/TypeScript#41383中所述,如下所示:Omit<T, K>
和NestedOmit<T, K>
之间的差异发生在Map的属性值类型内部,而不是键。由于
NestedOmit
的属性是按照NestedOmit
编写的,所以它是一个递归定义的类型。StripKey<T, P>
的思想是将当前键P
和K
的每个联合成员的开头的一个点进行跳转,或者如果成员不是以P
和点开头,则完全抑制该成员。它使用一个分布式条件类型来独立地操作K
的每个联合成员,并使用模板文字类型推断来解析字符串。让我们看看这部分的操作:您可以看到,如果您将
NestedOmit<{a: XYZ}, K>
与K
作为"a.b" | "a.c.d" | "e" | "e.f" | "e.g", "a"
调用,则a
属性最终将成为NestedOmit<XYZ, "b" | "c.d">
。这就是它的工作原理。让我们在你的例子中测试一下:
该类型是正确的,但显示可能不是您想要看到的,因为它是显式地以
NestedOmit
的形式编写的。如果重要的话,我们可以使用How can I see the full expanded contract of a Typescript type?中描述的技术来使NestedOmit
完全扩展其类型:⋯ extends infer O ? { [P in keyof O]: O[P] } : never
就是实现这一点的部件。现在我们看到:这正是你想要的
Playground代码链接