The function* declaration (function keyword followed by an asterisk) defines a generator function, which returns a Generator object. [Reference]
But if I do:
const genFn: GeneratorFunction = function* () {};
I get:
Property '[Symbol.toStringTag]' is missing in type '() => Generator<never, void, unknown>' but required in type 'GeneratorFunction'.ts(2741)
lib.es2015.symbol.wellknown.d.ts(161, 14): '[Symbol.toStringTag]' is declared here.
What does the GeneratorFunction interface stands for in TypeScript? Also, is there a more appropriate built-in interface for me to capture generator functions?
Here are a general four levels of annotations. All of these will compile without errors:
// Truly general
const genFnA: Function = function* () {};
// Bit less general
const genFnB: () => Generator = function* () {};
// Exact manual
const genFnC: () => Generator<never, void, unknown> = function* () {};
// Best: Use the inference
const genFnD = function* () {};
This is a very strange collision of how well-known Symbols and Generators were added to the Typescript type system. In the original proposal for Symbols, Anders Hejlsberg proposed the following:
interface Object {
[Symbol.toStringTag]: string;
}
which is a very reasonable way to enable everyone to set the Symbol.toStringTag
on every object, and in fact that is how this well-known Symbol is intended to be used. For reasons I cannot reconstruct, this was however not added to the Object
interface and not even to the Function
interface, but only to the GeneratorFunction
interface. Thus functions are not assignable to generator functions, though they are actually equivalent (both can be called).
The second strange thing here is that a function*
expression evaluates to () => Generator
and not to GeneratorFunction
. One should assume that those are equivalent, though due to the missing Symbol.toStringTag
they aren't.
Thus we cannot assign function*
s to GeneratorFunction
, although they are supposed (and actually are) describing the same type, which makes the GeneratorFunction
interface pretty much useless.
This is either a result of various constraints I do not see, or a bug in the Typescript types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With