1

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

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

OMG thank you now I get it why it was not working

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.