strblr
strblr

Reputation: 960

Method overload not specific enough

I have this code :

declare class Demo<T extends { [key: string]: any }> {
    find<K extends keyof T>(key: K): Array<T[K]>;
    find(key: string): any
}

const demo1 = new Demo<{ foo: number }>();
const result1 = demo1.find('foo'); // correct (number[])
const result2 = demo1.find('fooo'); // correct (any)

const demo2 = new Demo();
const result3 = demo2.find('test'); // incorrect (any[]), should be any

Playground

The comments might speak for themselves, but basically I would like the second overload to be considered for any find call when no generic was passed to Demo. Sadly, "test" satisfies the constraint keyof { [key: string]: any }, thus the first overload is called. How could I solve this problem ? Thank you.

Upvotes: 2

Views: 56

Answers (1)

Oblosys
Oblosys

Reputation: 15136

If it is not a problem to make the class slightly more general, you can constrain T to object instead of {[key: string]: any} to avoid the index-signature issues. An extra & string in the first find constraint will prevent it matching non-string keys:

declare class Demo<T extends object> {
    find<K extends keyof T & string>(key: K): Array<T[K]>;
    find(key: string): any
}

const demo1 = new Demo<{ foo: number }>();
const result1 = demo1.find('foo'); // correct (number[])
const result2 = demo1.find('fooo'); // correct (any)

const demo2 = new Demo();
const result3 = demo2.find('test'); // correct (any)

TypeScript playground

Upvotes: 2

Related Questions