5

I've been trying to make function overloads so my IDE could autocomplete the second paramater's type correctly based on the first argument's value. See example below:

class Animal {
    constructor(private name: string) { }

    bark(key: 'said', data: {
        text: string;
    }): void;
    bark(key: 'barked', data: {
        times: number;
    }): void;
    bark(key: 'said' | 'barked', data: any): void {
        if (key === 'said') console.log(`${this.name} said ${data}`);
        if (key === 'barked') for (let i = 0; i < data; i++) console.log('BARK!');
    }
}

const barry = new Animal('Barry');
barry.bark('barked', {
    /* Should auto-complete to { times: number } */
})

However the IDE autocompletes to both types for 'barked' and 'said'. See following example executed on Typescript sandbox

Code

Am I typing it incorrectly? Or perhaps expecting something that is not supported? Thanks!

2
  • Do your doubt it is about if I use certain param like cake the second would need to be milk? It is an example Commented Aug 21, 2020 at 22:20
  • @VagnerWentz Pretty much, I'm strong typing that function so depending on the first parameter's value (say cake), the IDE should know the second parameter expects a type based on cake and autocompletes it accordingly. Commented Aug 21, 2020 at 23:27

1 Answer 1

2

Great question. it seems Typescript is unable to infer the narrowest type (from the first parameter) when working with overloads.

One way to achieve what you want is by using Generics. here is how it can be done in your case:

type Type1 = {text: string}
type Type2 = {times: number}

class Animal {
    constructor(private name: string) { }

    bark<Key extends "said" | "barked", Data extends (Key extends "said" ? Type1 : Type2)>
    (key: Key, data: Data) : void;
    bark(key: any, data: any): any {
        if (key === 'said') console.log(`${this.name} said ${data}`);
        if (key === 'barked') for (let i = 0; i < data; i++) console.log('BARK!');
    }
} 

    
 const barry = new Animal('Barry');
 barry.bark("barked", {times: 5})

Although this works fine in your case, but it's not quite straightforward.

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

Comments

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.