Hvordan unngå void-type i generatorer i Typescript


Jeg bruker en generator i koden min, som returnerer strenger, men jeg står overfor følgende problem:

const pageUrl = generator.next().value;
const result = catalogPageParser(pageUrl);

Returnerer feilen:

Argument of type 'string | void' is not assignable to parameter of type 'string'.
  Type 'void' is not assignable to type 'string'.ts(2345)

Dette kan enkelt fikses ved enten å endre variabelen slik:

const pageUrl = generator.next().value ?? "some valid url";

Eller ved å endre signaturen til catalogPageParser-funksjonen. Jeg liker ingen av de løsningene, men jeg kan ikke komme på noe annet. Noen ideer om hvordan man kan skrive det korrekt?

Jeg liker ikke standardverdi-alternativet fordi det ikke finnes en rimelig standardverdi i mitt tilfelle. Jeg liker heller ikke det andre fordi det ikke gir mening i det hele tatt for funksjonen å akseptere void som et mulig argument.

Eksempel

function* someGenerator() {
  yield "url1";
  yield "url2";
}

function acceptsStringOnly(argument: string) {
  console.log(argument);
}

const value = someGenerator().next().value;
acceptsStringOnly(value);

Svar #1

Det er fordi resultatet av en iterator ikke kan ha en verdi hvis den allerede har avsluttet. I disse tilfellene er egenskapen done false. TypeScript kan automatisk begrense typen til value-egenskapen hvis du sjekker done:

function* generator() {
    yield 'string1';
    yield 'string2';
    yield 'string3';
}

const iterator = generator();
const result = iterator.next();

let theString: string;

// This fails as in your example
theString = result.value;

if (!result.done) {
    // this works
    theString = result.value;
} else {
    // whatever you have to do if the iterator has ended
}

Så løsningen på saken din kan være: 1) sjekk først om done er true og handle deretter (tidlig retur, kast, hva enn du trenger); 2) hvis du vet at iteratoren alltid vil returnere en verdi, kan du bruke en ikke-null-assertion.


Din nåværende løsning som bruker ?? er sannsynligvis også en god løsning, men det avhenger selvfølgelig av dine behov. En ulempe jeg kan tenke meg er at du ikke har en ordentlig standardverdi i den konteksten. Å håndtere tilfellet der iteratoren er ferdig, er etter min mening en bedre tilnærming i det generelle tilfellet.

Relaterte artikler