ts-essentials: Unable to use DeepOmit with generic type
export type ProducerOptions = DeepOmit<ProducerDocument, EntityOmit>;
export type ProducerDocument = DeepOmit<
// eslint-disable-next-line @typescript-eslint/ban-types
OmitProperties<ProducerAggregateRoot, Function>,
AggregateOmit
>;
Type 'AggregateOmit' does not satisfy the constraint 'DeepModify<T>'.
Type 'AggregateOmit' is not assignable to type 'T extends WeakMap<infer K extends object, infer E> ? WeakMap<K, DeepModify<E>> : never'.ts(2344)
I’m repeatedly doing this
export interface Entity<Id> {
id: Id;
createdAt: Date;
modifiedAt: Date;
}
export type EntityOmit = DeepReplace<Entity<never>, never>;
export type AggregateOmit = {
autoCommit: never;
[index: symbol]: never;
};
all extend AggregateRoot
this doesn’t work though
export type OmitIt<T extends AggregateRoot> = DeepOmit<
// eslint-disable-next-line @typescript-eslint/ban-types
OmitProperties<T, Function>,
AggregateOmit
>;
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 16
It’s released just now as a part of v10.0.0
The PR https://github.com/ts-essentials/ts-essentials/pull/384 was just merged, the changes will be released by the end of April as major - https://github.com/ts-essentials/ts-essentials/pull/386
There are different approaches that I came up with:
Another type
UnsafeDeepOmit– https://tsplay.dev/WylaKm – analogue forDeepOmit, but there’s not generic constraint appliedAdvantages – works with generic type Disadvantages – doesn’t highlight the typo if any, 2 types instead of one
Another type + generic constraint
UnsafeDeepOmit– https://tsplay.dev/W4XEKW + added generic constraint for generic type to force using generic constraint in your case, e.g.Record<"id" | "isLatest" | "checkId" | "createdAt" | "updatedAt", any>Advantages – works with generic type, highlights the typo if any (more strict) Disadvantages – still 2 types
I’m also happy to rename it to
GenericDeepOmitand highlight the usage in documentationI couldn’t come up with the solution where I can combine both approaches (as it’s unlikely possible, as we cannot use generic constraint for both generic type 1 and filter type)
I’m open for the feedback @Nightbr @xenoterracide , let me know about the name and the approaches that I suggested. Do you have other approaches preferable, could you please explain why?
In case there are some significant changes suggested, that’s what
Deep-types currently support:DeepModify)DeepModify)I would want to keep this functionality (and it’s covered with tests)
@Nightbr not a problem at all, I made the change major (addressed it in https://github.com/ts-essentials/ts-essentials/pull/384/commits/530b7a78680ba73268e7b3339a3122252e928387) to be absolutely clear
Thanks again for the detailed answer and explanation. Understood the decision and implication, I would still recommend introduce the changes as a major version. In my own use-case, It will work perfectly with our usage (with no BC) so thanks a lot!
It wouldn’t be a BC as I’m removing a generic constraint on the second type parameter of
DeepOmitandDeepPick. It would be a breaking change if it introduces a new TypeError but instead, it’s removing the validating part against a structure of the first parameter typeTypewhich doesn’t affect existing users.If it’s still treated as a break of contract (which I accept), I can introduce this change as a major version - https://github.com/ts-essentials/ts-essentials/pull/384/files#r1555086601. Aligning names and convention would be a priority right now because it was never done before or if it was done, it wasn’t documented anywhere.
Generic*prefix would be a new convention and will be only semantic. I find it quite misleading because it also works for non-generic cases. So as a user, I would be very confused about what to use so I would need to go to docs and read it anyway.With regard to
Strict*prefix, it is used when the additional generic constraint is applied to the utility type parameter, e.g.StrictOmit<Type, Keys>adds a generic constraint forKeys extends keyof Typeto be able to pass only existing keys. It will have the same side effect on generic types which is why it was removed from built-in types in TypeScript. The exact term name is to be clarified. Still, given this term is already used in ts-essentials, it would be consistent for users to continue using it instead of adding another convention on top of it.To add on top of it, one big advantage of my approach (with potential break of contract) is performance (see https://github.com/ts-essentials/ts-essentials/pull/384/files#r1555086934) -
DeepPickwould avoid a generic constraint which will simplify the conditional types a lot (it’s still not done in the PR but it would cut half of the size andStrict*version would only add one generic constraint). If doing other way round, it wouldn’t achieve the same result.PR is in progress - https://github.com/ts-essentials/ts-essentials/pull/384, please let me know if you have any input cc @xenoterracide @Nightbr
Thanks a lot for this very detailed exploration. My preference goes to
GenericDeepOmitand highlight the usage in documentation.Add to that, I’m ok that
DeepOmitdoesn’t work with not typed generic but maybe we could find a way to make it work when generic extend a defined type.https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgEQKarAeRMeBfOAMyghDgHIYBnAWlSqtQDsZgBDAGyvIG4BYAFCCYATzCo4AcWaoowAMYBhABap5Aa2RsYbOAF5EguHGAATAFxwqMOUwDm-AceBUAMtvoxLAIwgQOqGxMjsbyqhoAkhZWNsD2IXDyUIEwqKYAgl4oHgkArmCmHhlZWqmOeIKCqAAekLBwouJwAKK1EIymKmqa2mwAPAAqcDWpTKZUUjJySuE9OgB8+ijoWDgwfUZwAwA0mwiboclFmZZMqABusgnG+YWpxacXV5sVAvOOQA
Did you explore with the extends on Generic?
Thank you for the playground link @Nightbr, I will spend time this week to have a look at it
Same here, cannot be able to DeepOmit on generic:
Here is a TypeScript playground: https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgEQKarAeRMeBfOAMyghDgHIYBnAWlSqtQDsZgBDAGyvIG4BYAFCDUAD0iw4MAJ5hUcAKJiIjACYBhABaoAxgGtkbGGwA8AFQB8cALwp0WHDGOC4cUwBpniTy+AqAXHBMqABuqFD8Ai4+VAAyhvQwAUGh4d5w2lp6AJL+gSFhEVHpUKjxKgCCiXkphVEArmAqZZVJ+amRcHiC5hFAA