Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the GeneratorFunction interface stands for in TypeScript?

Tags:

typescript

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?

like image 630
villasv Avatar asked Jan 25 '23 17:01

villasv


2 Answers

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* () {};
like image 126
basarat Avatar answered Feb 23 '23 00:02

basarat


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.

like image 37
Jonas Wilms Avatar answered Feb 23 '23 00:02

Jonas Wilms