Describe a deeply nested array in TypeScript

狂风中的少年 提交于 2020-01-23 06:19:58

问题


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?


回答1:


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!!!


来源:https://stackoverflow.com/questions/40602784/describe-a-deeply-nested-array-in-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!