In the Abstract Syntax Trees Overview, the code for the article presented a set of distinct types for defining a very basic AST. These types each manually redefined the entire representation of a TreeNode
, as pertained to the type in question. This is not only repetitious and prone to error, but it also reduces to possibility for these types to be more consistently generated automatically.
Is it possible, in TypeScript, to generate types automatically, and have them define, very loosely, a series of interrelated connections? Certainly, as has been seen previously in the discussion of Generics. Perhaps it would be possible to utilize some of the techniques previously discussed here, and thus redefine the type structure of the AST; this would also allow for easy and rapid expansion of the set of types the system could support.
As a refresher, recall that a type in TypeScript represents the set of known behaviors of the data it is said to represent. As such, it describes the fields and operations that are permissable on the type. A type can also be the composite of multiple existing types, via use of the &
, type intersection combination operator. With this operator, subsequent types in the list will add their fields to the type definition built in previous stages; should this process hit a duplicate field name, the most recent instance will overwrite.
Generic type definitions can use this functionality to establish a base type—such as TreeNode
—and extend its functionality via a series of overrides, some of which might be contextually programmed into the generic via a generic type parameter. This can simplify the definition of a new derivative type, limit the repetition of specifying certain types of fields, ensure that all fields within a type are readonly, and also limit the impact of mistyping key string literals.
With this minor restructure in hand, defining new derived types to add to the system is comparably trivial: typically, a simple one-liner that invokes a single generic type, passing a single string-based type parameter. This allows the types, and their data, to be handled in a nicely uniform fashion, largely consistent across the ensuing system. Also, should the need arise to expand or alter some aspect of the type system, these edits will be easier to address.