I want to to create a generic type that omits properties defined elsewhere. Something like this:
type WriteOnlyFields = {
OrganizationDto: "type",
PersonDto: "nationalIdentifier"|"creationFlag"
}
// Does not work, because WriteOnlyFields must be indexed with string
type Output<T> = Omit<T, WriteOnlyFields[T]>;
// This should now give a compilation error, bacause "type" is omitted
const organization: Output<OrganizationDto> = {
type: "organization"
}
I plan to use this in a scenario where the WriteOnlyFields
type is generated. What I don't want to do is to generate types like Output_Organization
and Output_Person
.
It seems like the most straightforward solution would involve transforming WriteOnlyFields[T]
into WriteOnlyFields[nameof T]
, but I can't find a way to do this in Typescript
Types do not have "names" that you can turn into string types. That means that you can't really do this as you want to.
To do that, you'd have to do something like:
Which works, but sure ain't elegant. This structure also feels like it doesn't respect the encapsulation of each type. The type should know what's write only, not some global type object.
One very simple idea is to create two types that extend each other: (This is what I do in my NestJS projects)
This way you never have to declare the same property twice, but you do have two distinct types for input and output, which you don't seem to want.
There's a lot of ways to do something like this, but for a more generic approach that's closer to you initial attempt, then the type must have enough information to resolve itself. That means it needs to be able find all its own fields.
Let's say you changes
OrganizationDto
to something like:Here you nest the two sets of fields in the type itself. Now you can define two simple type aliases to manage these, which you would use everytime you wanted to use these types:
The downside here is that you can't really use
OrganizationDto
directly anymore, and must always rely on theInput
andOutput
types to transform it for use. And that probably makes this solution add more complexity than it resolves.Playground