Родовая функция с правильной подписью - PullRequest
0 голосов
/ 21 марта 2019

Я не знаю, как объявить второй параметр функции boom для правильной проверки типа, я имею в виду, что если кто-то отправляет первый параметр функции boom как "foo1", то второй параметр должен быть возможен только как: (number) => void , Если "foo2", то (string) => void.

interface MyFoo {
    foo1: (number) => void;
    foo2: (string) => void;
}

class Bar<Foo> {
    public boom<T extends Foo, K extends keyof MyFoo>(first: K,
        ...args: Parameters<T[K] /* here I don't know how to declare this parameter */){

    }
}

new Bar<MyFoo>().boom("foo1", /* callback with signature: (number) => void */)

1 Ответ

2 голосов
/ 21 марта 2019

Прежде всего, обратите внимание, что имена параметров в типах функций обязательны , поэтому это определение необходимо изменить:

interface MyFoo {
    foo1: (x: number) => void; 
    foo2: (x: string) => void;
}

Теперь в Bar<Foo> нам нужен только один универсальныйпараметр K в методе boom(), поскольку для нас будет указан тип Foo.Я не совсем понимаю ваш вариант использования, поскольку он выглядит как возможно , вы хотите, чтобы boom() принимал переменное число параметров, но это не соответствует комментарию о том, как вам нужна функция обратного вызова.Поэтому я предполагаю, что boom() принимает два параметра: имя ключа и функцию обратного вызова:

class Bar<Foo> {
    public boom<K extends keyof Foo>(first: K, second: Foo[K]) { }
}

И вот как вы его используете:

// okay, the callback is (x: number) => void
new Bar<MyFoo>().boom("foo1", (x: number) => console.log(x.toFixed(2)));

// error, the callback is (x: number) => void but should be (x: string) => void
new Bar<MyFoo>().boom("foo2", (x: number) => console.log(x.toFixed(2))); 

Кстати, этоне мешает вам использовать интерфейс с нефункциональными свойствами:

interface MyFoo { age: number }
new Bar<MyFoo>().boom("age", 40); // okay

Если вам требуется, чтобы boom() работал только с клавишами, соответствующими функциональным свойствам, вам понадобится какой-нибудь изумительный условные типы :

type KeysMatching<T, V> =
    Extract<keyof T, { [K in keyof T]: T[K] extends V ? K : never }[keyof T]>;

class Bar<Foo> {
    public boom<K extends KeysMatching<Foo, Function>>(first: K, second: Foo[K]) { }
}

// okay, the callback is (x: number) => void
new Bar<MyFoo>().boom("foo1", (x: number) => console.log(x.toFixed(2)));

// error, the callback is (x: number) => void but should be (x: string) => void
new Bar<MyFoo>().boom("foo2", (x: number) => console.log(x.toFixed(2))); 

interface MyFoo { age: number }

// error, "age" is not accepted anymore
new Bar<MyFoo>().boom("age", 40); // error

Надеюсь, что вам это поможет.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...