Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript: Get correct value type from object by key generic

in the example I want to write an simple query builder where all types of an entity are correctly casted. For example when im filtering with equalsTo for name I only want to allow strings as values, same for age there should only be numbers allow. Now value can be any value of Dogs and thats not what I want. Can somebody help me is this possible?

class Dogs {
    name!: string;
    age!: number;
    alive!: boolean;
}
interface QueryBuilder<O extends object, F extends keyof O = keyof O> {
    equalsTo: (fieldName: F, value: O[F]) => boolean;
}
const queryBuilder = <O extends object>(): QueryBuilder<O> => ({
    equalsTo: (fieldName, value) => true 
})
const qb = queryBuilder<Dogs>();
qb.equalsTo("name", 1); // Should throw an error that only string is allowed as value
qb.equalsTo("age", "Rex"); // Should throw an error that only number is allowed as value

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Your interface definition:

interface QueryBuilder<O extends object, F extends keyof O = keyof O> {
    equalsTo: (fieldName: F, value: O[F]) => boolean;
}

is allowing the second parameter of equalsTo to be string | number | boolean because TypeScript can’t narrow the type any further at the class level.

However – if you type-annotate the function itself:

interface QueryBuilder<O extends object> {
    equalsTo: <F extends keyof O = keyof O>(fieldName: F, value: O[F]) => boolean;
}

… you get the behaviour you’re looking for:

qb.equalsTo("name", 1); // Argument of type 'number' is not assignable to parameter of type 'string'.(2345)

qb.equalsTo("age", "Rex"); // Argument of type 'string' is not assignable to parameter of type 'number'.(2345)


TypeScript playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading