Say I have the type
type Atom = string | boolean | number
. I want to define a type of array like:
NestedArray = Atom | [a_0, a_1, ... , a_n]
where each a_i
is an Atom
, or a NestedArray
.
Can this be achieved in Typescript?
TypeScript does not optimize tail-called recursive functions.
Recursion is a process of calling itself. A function that calls itself is called a recursive function. The syntax for recursive function is: function recurse() { // function code recurse(); // function code } recurse();
In computer programming languages, a recursive data type (also known as a recursively-defined, inductively-defined or inductive data type) is a data type for values that may contain other values of the same type. Data of recursive types are usually viewed as directed graphs.
Type aliases can't reference themselves, so this naïve approach will fail:
type NestedArray = Atom | Array<NestedArray | Atom> //Type alias 'NestedArray' circularly references itself.
Interfaces can however reference themselves:
interface NestedArray extends Array<NestedArray | Atom> {
}
And we can define an extra union at the top level to handle the root case:
type Atom = string | boolean | number
interface NestedArray extends Array<NestedArray | Atom> {
}
type AtomOrArray = Atom | NestedArray;
//Usage
let foo: AtomOrArray = [
"",
1,
[1, 2, ""]
]
let bar: AtomOrArray = ""
Now typescript allow type circularly references itself, such like this:
type RArray = (string | RArray)[];
And if you want to define a generic type in recursive function, can use interface ...<T> extends (T|...<T>)[]
interface RA<T> extends Array<T | RA<T>> { }
For example, create a function to get sum recursivily
function sum(arr: RA<number>) {
let res = 0;
arr.forEach((n) => {
if (Array.isArray(n)) {
res += sum(n);
} else {
res += n;
}
});
return res;
}
console.log(sum([1, 2, 3, [4, [5]], [[6]]]))
// output: 21
But this way has some disadvantage, compiler can't know the specific type of n
arr.forEach((n) => {
if (Array.isArray(n)) { // typeof n: `number | RA<number>`
res += sum(n);
} else {
res += n;
}
});
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