Typescript: Omit And Projection Types
Typescript 2 introduced a number of useful mapped types such as Pick
or Partial
. However sometimes the predefined ones just don't cut it. Here's two new types you can use to make your life easier.
Omit
Pick
is handy when you need to create a new type from an existing interface with only the specified keys. Which is great but sometimes you need just the opposite. Like when you're defining the return type for your API endpoint where you want to include everything except for one or two private fields.
Using Pick
for that gets awkward very fast. You can use Partial
but that throws typechecking out of the window.
So what you actually need is Omit
. Here it is:
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;
(Update: Thanks to Andrew Bradley for his comment below about homomorphic transformation; snippet updated)
Now you can do things like:
type TCleanedUser = Omit<IUser, 'privateField1' | 'privateField2'>;
Note: The original author of this is @tycho01 and the code was taken from this GitHub issue.
Projection (i.e., typesafe Mongo projection specifier)
If you use MongoDB it's pretty useful to be able to typecheck your projection specifiers, i.e., which fields should - or should not - be returned in the result. To do that, you can use this mapped type:
type Projection<T> = Partial<Record<keyof T, 0 | 1>>;
Now you can write code like
MyCollection.find({}, {importantField: 1: anotherImportantField: 1} as Projection<IMyDoc>);
Well at least till typed projection gets into the typings for your favourite Mongo driver by when you can just forget about this. :-)
Happy typechecking! I'm @tomas_brambora.