【发布时间】:2022-08-18 16:06:40
【问题描述】:
我们在以下界面上工作
interface A {
a: string
b: string
c?: number
d?: number
}
而且我们有一种类型可以使T 中的每个键可选的如果他们的类型是 string 并且必需的如果是number
type B<T> = {
[K in keyof T as T[K] extends (number|undefined) ? K : never]-?: T[K]
} & {
[K in keyof T as T[K] extends (string|undefined) ? K : never]+?: T[K]
}
/* The resulting type will be:
type B<A> = {
c: number;
d: number;
} & {
a?: string | undefined;
b?: string | undefined;
}
*/
但是,如果我们将正在处理的接口更改为仅包含条件中指定的类型之一,{},它几乎对应于any 将被添加到结果类型
interface A1 {
a: string
b: string
}
/* The resulting type will be:
type B<A1> = {} & {
a?: string | undefined;
b?: string | undefined;
}
*/
这将允许将许多不需要的类型分配给 B,从而破坏目的。例如
const b: B<A1> = \"We don\'t want this to happen.\" // <-- We need an error here.
问题
如何防止生成的类型包含 {} ?我希望B<A1> 产生以下类型
{
a?: string | undefined;
b?: string | undefined;
}
游乐场链接
我通过删除泛型简化了类型,因此结果类型是可见的。你可以查看here
-
GitHub 跟踪器中有一些问题涉及与空对象的交集,但我没有发现这个特定问题。一种解决方法,试试这个助手(具有讽刺意味的是,它涉及与一个空对象相交):
type Expand<T> = {} & { [P in keyof T]: T[P] }; -
谢谢你。我自己很难找到这个修复程序。我应该就此提出问题还是预期的行为?我认为您可以使用此解决方法发布答案,也许可以解释其工作原理。
-
我很惊讶这还没有被报道(社区非常积极地报道这种事情),但如果你没有找到它,你可以试试。顺便说一句,这也应该有效:
type Expand2<T> = { [P in keyof T]: T[P] };。对我来说它看起来像一个错误,如果您粘贴类型C并使用它,那么它就可以工作,这对我来说毫无意义。 -
实际上是works。如果您发布答案,我会接受。
-
@soffyo 我认为这是根本问题:github.com/microsoft/TypeScript/issues/42864。如果您创建
type D = {[K in never]: any} & {a?: string | undefined, b?: string | undefined},您会看到它也显示为{} & {...},并表现出与C相同的行为。