Search code examples
typescriptmapped-types

How to add a type constraint to a mapped type?


I am trying to add more typings to MongoDB query system.

I have an object

interface Person { name: string; age: number }

I want to create a query object that allows the operator $gt only on the age field because it is a number, not the name field.

{ age: { $gt: 21 } } would be valid, but not { name: { $gt: 21 } }

Something like

type MongoConditions<T> = {
    [P in keyof T]?: T[P] |
    { $gt: number }; // This condition should be allowed only if T[P] is a number
};

So this should be allowed

const condition: MongoConditions<Person> = {
    age: { $gt: 21 },
    name: 'foo'
}

But this should fail the compilation:

const condition3: MongoConditions<Person> = {
    age: 21,
    name: { $gt: 21 }
}

Solution

  • You can use conditional type to allow query operator only on "number" field:

    type MongoConditions<T> = {
        [P in keyof T]?: T[P] extends number ? (T[P] | { $gt: number }) : T[P];
    };
    

    Playground