How do I define a type or interface describing a deeply nested array in TypeScript?
For example, let's say I am writing a function for testing a path against any number of patterns.
function match(path: string, matcher: Matcher): boolean { /* ... */ }
The Matcher
type may be any of the following:
string
RegExp
Matcher[]
(note the self-reference)In other words, the compiler should accept the following:
match('src/index.js', 'lib/**/*');
match('src/index.js', /\/node_modules\//);
match('src/index.js', ['src/**/*', /\.js$/]);
match('src/index.js', ['src/**/*', [/\.js$/, ['*.ts']]]);
But the following should produce a compiler error:
match('src/index.js', {'0': 'src/**/*'}); // Compiler Error!!!
match('src/index.js', ['src/**/*', true]); // Compiler Error!!!
match('src/index.js', ['src/**/*', [/\.js$/, [3.14]]]); // Compiler Error!!!
Is there a way to achieve this in TypeScript?
You could also use a type to define a two-dimensional array. Copied! type Nested = number[][]; const arr: Nested = [ [1, 2, 3], [4, 5, 6], ]; If you have an object with a property that is a two-dimensional array, you can also use an interface.
Nested Array in JavaScript is defined as Array (Outer array) within another array (inner array). An Array can have one or more inner Arrays. These nested array (inner arrays) are under the scope of outer array means we can access these inner array elements based on outer array object name.
Use an interface or a type alias to type a nested object in TypeScript. You can set properties on the interface that point to nested objects. The type of the object can have as deeply nested properties as necessary.
There is no difference at all. Type[] is the shorthand syntax for an array of Type . Array<Type> is the generic syntax. They are completely equivalent.
Yes, you can do this in TypeScript. The solution is a bit verbose, but it can be done using a combination of generic type aliases and interfaces.
Start with an interface defining a deeply nested array.
interface DeepArray<T> extends Array<T | DeepArray<T>> { }
So far, the compiler will accept the following:
type Matcher = DeepArray<string | RegExp>;
const m1: Matcher = ['src/**/*', /\.js$/];
const m2: Matcher = ['src/**/*', [/\.js$/, ['*.ts']]];
But the question specifies that the function should also accept a single string
or RegExp
. This
will still produce a compiler error.
const m3: Matcher = 'lib/**/*'; // Compiler Error!!!
const m4: Matcher = /\/node_modules\//; // Compiler Error!!!
We can solve this problem with a generic type alias:
type Deep<T> = T | DeepArray<T>;
And now our type works as expected.
type Matcher = Deep<string | RegExp>;
function match(path: string, matcher: Matcher): boolean { /* ... */ }
match('src/index.js', 'lib/**/*');
match('src/index.js', /\/node_modules\//);
match('src/index.js', ['src/**/*', /\.js$/]);
match('src/index.js', ['src/**/*', [/\.js$/, ['*.ts']]]);
match('src/index.js', {'0': 'src/**/*'}); // Compiler Error!!!
match('src/index.js', ['src/**/*', true]); // Compiler Error!!!
match('src/index.js', ['src/**/*', [/\.js$/, [3.14]]]); // Compiler Error!!!
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