All of the answers here are dated as far as I can tell. In 2022 I just used the following to recursively scan a directory and save all the files and directories returned by the scan:
type AbstractDirectory = {
pathname: string;
files: string[];
};
type AbstractFileTree = string | string[] | {
[ key: string ]: AbstractFileTree;
dirpath: string;
filepaths: string[];
};
Perhaps the most common need for recursive types, is the need to use a true JSON type. The JSON data format needs is infinitely recursive, therefore, any generics used to represent the format need to be able to handle an infinite amount of recursion. Any finite representation would be less than adequate.
In older versions of TypeScript (pre v3.7) JSON generics were defined using the following:
type Json = string | number | boolean |
null | JsonObject | JsonArray;
interface JsonObject {
[property: string]: Json;
}
interface JsonArray extends Array<Json> {}
A good example that was included in the `v3.7 release notes is demonstrated in the following snippet, which is a great solution to any recursive typing that you might be doing.
As of v3.7 or newer, the following is valid TypeScript:
type Json =
| string
| number
| boolean
| null
| { [property: string]: Json }
| Json[];
Both examples are recursive, but the later is a cleaner, easier to remember, and is a more accurate abstract representation of the JSON interchange format as defined by ECMA-404.