Eu tenho a seguinte função geradora:
async function * filterIterable (iter, predicate) {
let i = 0
for await (const val of iter) {
if (predicate(val, i++)) {
yield val
}
}
}
que eu gostaria de digitar para os dois casos a seguir:
// type predicate
const nonNullable = <T>(val: T | undefined | null): val is T =>
val !== undefined && val !== null
async function * gen1 () {
yield 1
yield 2
yield 3
}
async function * gen2 () {
yield 1
yield undefined
yield 3
}
const it1 = filterIterable(gen1(), n => n % 2 === 0)
const it2 = filterIterable(gen2(), nonNullable) // should be AsyncIterable<1 | 2>
Eu criei esta interface:
interface FilterIterable {
<T> (
iter: AsyncIterable<T>,
predicate: (val: T, index: number) => boolean,
): AsyncIterable<T>;
<T, S extends T> (
iter: AsyncIterable<T>,
predicate: (val: T, index: number) => val is S,
): AsyncIterable<S>;
}
que eu poderia aplicar a uma expressão de função, mas aparentemente não a uma declaração de função de acordo com Como aplicar um tipo de função a uma declaração de função . Não é isso que o gerador é?
Então você quer
filterIterable()
ser uma função sobrecarregada com múltiplas assinaturas de chamada. Embora seja verdade que atualmente você não pode anotar diretamente uma função conforme solicitado em microsoft/TypeScript#22063 , você pode simplesmente usar a sintaxe de sobrecarga regular e declarar as assinaturas de chamada antes da implementação:Agora isso deve funcionar como você pretendia:
Link do Playground para o código