I am trying to set default properties using Omit<>
in typescript and append more via generics.
For example, I want to exclude a set of properties by default and have the user choose more to exclude by using Omit<>
type OmittedEntity<TEntity extends IBaseEntity, TExtraOmissions extends (keyof TEntity) | void = void> = TExtraOmissions extends keyof TEntity ? Omit<TEntity, "id" | "collection" | TExtraOmissions> : Omit<TEntity, "id" | "collection">
interface IBaseEntity {
id: string;
collection: string;
status: string;
}
// My new Entity
interface ISomeEntity extends IBaseEntity {
firstName: string;
lastName: string;
middle: string;
}
When trying to exclude one more property than OmittedEntity<>
does, every works perfectly
const e: OmittedEntity<ISomeEntity, "firstName"> = {
lastName: "",
middle: "",
status: ""
}
When trying to exclude two or more properties than OmittedEntity<>
does, I do not get the desired result. Typescript wants me to choose between omitting firstName
or lastName
const e: OmittedEntity<ISomeEntity, "firstName" | "lastName"> = {
lastName: "", // Error
firstName: "", // Error
middle: "",
status: ""
}
How to I get the above example to allow me to exclude both properties, not one or the other?
I essentially want
const e: OmittedEntity<ISomeEntity, "firstName" | "lastName"> = {
middle: "",
status: ""
}
CodePudding user response:
You need to disable the distributivity of the conditional type.
type OmittedEntity<
TEntity extends IBaseEntity,
TExtraOmissions extends (keyof TEntity) | void = void
> = [TExtraOmissions] extends [keyof TEntity] ? Omit<TEntity, "id" | "collection" | TExtraOmissions> : Omit<TEntity, "id" | "collection">
Without the square brackets, the elements in TExtraOmissions
will be distributed to several Omits
.
Also, you could simplify the whole OmmitedEntity
type to this:
type OmittedEntity<
TEntity extends IBaseEntity,
TExtraOmissions extends (keyof TEntity) = never
> = Omit<TEntity, "id" | "collection" | TExtraOmissions>
I don't see any benefit of using void
here. We can just set the default to never
, so if no type is given this will be ommitted from the union.