Вы можете сузить ошибку компилятора, сделав еще одну абстракцию общих типов c.
Вторая абстракция будет отвечать за фильтрацию массива по заданному типу.
const filterByType = <T>(arr: any[], key: keyof T): T[] =>
arr.filter(e => (<T>e)[key]) as T[];
После Руководство по типу скрипта о том, как ввести охрану экземпляра , мы вынуждены указать, какой ключ проверять, было ли преобразование выполнено эффективно (уникальный ключ в типе, по которому мы фильтруем).
Итак , теперь мы можем фильтровать в нашей функции по RefreshWithFoo
export const refresh = <
N extends HasRefresh | HasRefreshWithFoo,
RefreshWithFoo extends HasRefreshWithFoo,
RefreshNormal extends HasRefresh
>(
ns: N[],
foos: Foo[]
) => {
const refreshWithFoo: RefreshWithFoo[] = filterByType<RefreshWithFoo>(ns, `x`);
}
Без каких-либо жалоб компилятора.
Ну, я использую по умолчанию tsconfig , я полагаю, это не будет жаловаться с любой другой конфигурацией компилятора. Если да, дайте мне знать.
Edit
В некоторых случаях, например, при пересечении типов, вам потребуется более одного ключа для проверки. Вы можете просто расширить метод, ожидая массив ключей params и проверив их все, например, так
const filterByType = <T>(arr: any[], ...keys: (keyof T)[]): T[] =>
arr.filter(e => keys.every(k => (<T>e)[k])) as T[];
Надеюсь, это поможет.