[英]Delete object keys and return conditional type in Typescript
I have two interfaces to describe the different messages我有两个接口来描述不同的消息
interface MessageA {
timestamp: number
}
interface MessageB {
name: string
}
and an interface to describe their common fields和一个接口来描述他们的共同领域
interface CommonMessage {
text: string
url: string
}
And I combine them into a new type by adding extra fields with the type declared using const enum
我通过添加使用const enum
声明的类型的额外字段将它们组合成一个新类型
const enum Type {
A,
B,
}
type CombinedMessage =
| (MessageA & CommonMessage & { type: Type.A })
| (MessageB & CommonMessage & { type: Type.B })
Besides, I define a type that removes the common fields in the CombinedMessage
此外,我定义了一个类型,它删除了CombinedMessage
中的公共字段
type DistributiveOmit<T, K extends string & keyof T> = T extends any ? Omit<T, K> : never
type Message = DistributiveOmit<CombinedMessage, keyof CommonMessage | 'type'>
Now, I want to define a function to convert CombinedMessage
into Message
.现在,我想定义一个函数来将CombinedMessage
转换为Message
。
const omit = <T, K extends string & keyof T>(value: T, keys: readonly K[]): DistributiveOmit<T, K> => {
const ret = { ...value }
for (const key of keys) {
delete ret[key]
}
return ret
}
After omit
function is defined, I can define定义omit
函数后,我可以定义
function removeCommonFields(combinedMessage: CombinedMessage): Message {
return omit(combinedMessage, ['text', 'url', 'type'])
}
to get what I want.得到我想要的。
However, Typescript
compiler shows that the line但是, Typescript
编译器显示该行
return ret
in function omit
has errors that在函数中omit
有错误
Type 'T' is not assignable to type 'DistributiveOmit<T, K>'.ts(2322)
It shows that ret
here is the generic type T
, so I cannot return as the type DistributiveOmit<T, K>
.它表明这里的ret
是泛型类型T
,所以我不能作为DistributiveOmit<T, K>
类型返回。
It seems that delete
operation do nothing for the type of ret
.似乎delete
操作对ret
类型没有任何作用。
Currently, I use return ret as unknown as DistributiveOmit<T, K>
to avoid the compiler showing error;目前,我使用return ret as unknown as DistributiveOmit<T, K>
来避免编译器显示错误; however, I want to avoid using type assertion as possible as I can.但是,我想尽可能避免使用类型断言。
Is there any other ideas?还有其他想法吗? Thanks.谢谢。
This is more or less a design limitation of TypeScript.这或多或少是 TypeScript 的设计限制。 You can't really avoid type assertions here.在这里您无法真正避免类型断言。
The compiler defers evaluation of conditional types that depend on an as-yet-unspecified generic type parameters, and thus it cannot really verify that anything is assignable to such types.编译器推迟对依赖于尚未指定的泛型类型参数的条件类型的评估,因此它无法真正验证任何东西都可以分配给这些类型。
And while Omit<X, K>
is seen as a supertype of X
, and thus Omit<X, K> | Omit<Y, K> | Omit<Z, K>
而Omit<X, K>
被视为X
的超类型,因此Omit<X, K> | Omit<Y, K> | Omit<Z, K>
Omit<X, K> | Omit<Y, K> | Omit<Z, K>
Omit<X, K> | Omit<Y, K> | Omit<Z, K>
would be seen as a supertype of X | Y | Z
Omit<X, K> | Omit<Y, K> | Omit<Z, K>
将被视为X | Y | Z
的超类型X | Y | Z
X | Y | Z
, the compiler does not know how to generalize that distributivity to DistributiveOmit<T, K>
inside the body of omit()
where T
is unspecified. X | Y | Z
,编译器不知道如何将该分布推广到DistributiveOmit<T, K>
在omit()
的主体内,其中T
未指定。
There is an open feature request at microsoft/TypeScript#33912 asking for more compiler support with generic functions that return conditional types. microsoft/TypeScript#33912 上有一个开放功能请求,要求为返回条件类型的泛型函数提供更多编译器支持。 It doesn't look like there's any obvious solution to this in the near future, and even if there were it might not work in your particular example.看起来在不久的将来没有任何明显的解决方案,即使有它在您的特定示例中也可能不起作用。 So for the time being, the best you can do is a type assertion (or something equivalent like a single call-signature overload ).因此,就目前而言,您能做的最好的事情是类型断言(或类似单个调用签名重载的等效内容)。
The only slight improvement I can think of would be to use Omit<T, K>
instead of unknown
as your intermediate asserted type:我能想到的唯一轻微改进是使用Omit<T, K>
而不是unknown
作为您的中间断言类型:
return ret as Omit<T, K> as DistributiveOmit<T, K>; // no error
It would help catch errors where you return something other than ret
accidentally:这将有助于捕获您意外返回ret
以外的其他内容的错误:
// return "oopsie" as unknown as DistributiveOmit<T, K>; // no error
// return "oopsie" as Omit<T, K> as DistributiveOmit<T, K>; // error!
Which might be better than nothing, but not by much.这可能总比没有好,但也好不了多少。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.