简体   繁体   中英

How do you define multiple yield types in a TypeScript iterable?

I have an iterable and array destructuring that works but doesn't type check correctly. I'm pretty new to TypeScript so I'm guessing that I'm doing something wrong. I'm using TypeScript 3.8.2.

This example works because no type checking occurs, but uncommenting the last line causes the error below this code example to show up.

function MakeIterable<T> (a: T, b: number, c: boolean) {
    const result = [ a, b, c ]

    function* gen(): Generator<T | number | boolean, void, void> {
        let v
        while (v = result.shift()) {
            yield v
        }
    }

    return gen()
}

const [a, b, c] = MakeIterable(new Date(), 5, true)
console.log(a, b, c)
// a.setDate(0)

Error output after uncommenting a.setDate(0) :

Error:(16, 7) TS2339: Property 'setDate' does not exist on type 'number | boolean | Date'.
  Property 'setDate' does not exist on type 'number'.

Also, modifying the Generator definition to limit it to one returned type fixes it, but the second and third items off the iterator will not be the type that TypeScript thinks it is. TypeScript thinks all items must be Date objects in this case.

Modified example line:

function* gen(): Generator<T, void, void> {

Question: What is the correct way to define the different value types that come back from the iterator? Ideally the types in order (in this case T, number, boolean ) would be nice.

Type definition for Generator or Iterator does not support ordered sequence of return types - stricter generators . But also, logically, ordered sequence of return types would be broken more often then not.

It would work only in simplest cases, when next() is called within the same scope/file, sequentially, until the sequence ends. Given example is too trivial, so that generator can be omitted completely.

For example, if next() is called via event handler, or generator is shared between multiple components, specifying order of types would potentially lead to runtime errors. Therefore, union type T | number | boolean T | number | boolean T | number | boolean is appropriate output for generator.

Correct approach, to cover all use-cases, is to use type guards on returned values.

if (a instanceof Date) {
    a.setDate(0);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM