2016-11-15 56 views
2

如何在TypeScript中定義描述深度嵌套數組的類型或接口?在TypeScript中描述深度嵌套的數組

例如,假設我正在編寫一個函數來測試任意數量的模式的路徑。

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

Matcher類型可以是任何以下的:

  • string
  • RegExp
  • Matcher[](注意自參考)

換句話說,該編譯器應該接受以下內容:

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

有沒有辦法在打字稿實現這一目標?

回答

2

是的,你可以在TypeScript中做到這一點。該解決方案有點冗長,但可以使用通用類型別名和接口的組合來完成。

從定義深度嵌套數組的接口開始。

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

到目前爲止,編譯器將接受以下:

type Matcher = DeepArray<string | RegExp>; 

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

但問題指明函數也應該接受一個stringRegExp。這個 仍然會產生編譯器錯誤。

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

我們可以解決這個問題,一個泛型類型的別名:

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

而現在我們的類型按預期工作。

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