Búsqueda de sitios web

Describe un arreglo profundamente anidado en TypeScript


¿Cómo defino un tipo o interfaz que describa un arreglo profundamente anidado en TypeScript?

Por ejemplo, digamos que estoy escribiendo una función para probar un camino contra cualquier número de patrones.

function match(path: string, matcher: Matcher): boolean { /* ... */ }

El tipo Matcher puede ser cualquiera de los siguientes:

  • string
  • RegExp
  • Matcher[] (nota la autorreferencia)

En otras palabras, el compilador debería aceptar lo siguiente:

match('src/index.js', 'lib/**/*');
match('src/index.js', /\/node_modules\//);
match('src/index.js', ['src/**/*', /\.js$/]);
match('src/index.js', ['src/**/*', [/\.js$/, ['*.ts']]]);

Pero lo siguiente debería producir un error de compilación:

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

¿Hay alguna manera de lograr esto en TypeScript?

Respuesta #1

Sí, puedes hacer esto en TypeScript. La solución es un poco extensa, pero se puede hacer usando una combinación de alias de tipos genéricos e interfaces.

Comienza con una interfaz que defina un arreglo profundamente anidado.

interface DeepArray<T> extends Array<T | DeepArray<T>> { }

Hasta ahora, el compilador aceptará lo siguiente:

type Matcher = DeepArray<string | RegExp>;

const m1: Matcher = ['src/**/*', /\.js$/];
const m2: Matcher = ['src/**/*', [/\.js$/, ['*.ts']]];

Pero la pregunta especifica que la función también debería aceptar un solo string o RegExp. Esto todavía producirá un error del compilador.

const m3: Matcher = 'lib/**/*';         // Compiler Error!!!
const m4: Matcher = /\/node_modules\//; // Compiler Error!!!

Podemos resolver este problema con un alias de tipo genérico:

type Deep<T> = T | DeepArray<T>;

Y ahora nuestro tipo funciona como se esperaba.

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

Artículos relacionados