2017-03-24 6 views
3

Array.prototype.filterを使用して配列からヌル(未定義)要素をフィルタリングしようとしていますが、TypeScriptコンパイラが "filter"関数の派生配列を認識せず、型チェックに失敗しました。TypeScriptコンパイラに指示する方法Array.prototype.filterは配列から特定の型を削除しますか?

(number | undefined)[]型の配列を持ち、number []配列に収まるようにundefinedをフィルタしたい場合、次のような単純なコードを仮定します。

const arry = [1, 2, 3, 4, "5", 6]; 
const numArry: number[] = arry 
    .map((i) => { 
     return typeof i === "number" ? i : void 0; 
    }) 
    .filter((i) => i); 

エラーは言う:

タイプ '(数|未定義)[]' '番号を[]' 型に代入ではありませんが。 タイプ 'number | undefined 'は' number '型に割り当てられません。 タイプ 'undefined'はタイプ 'number'に割り当てられません。

私は結果の配列を数値[]にキャストすることができます。

const arry = [1, 2, 3, 4, "5", 6]; 
const numArry: number[] = (arry 
    .map((i) => { 
     return typeof i === "number" ? i : void 0; 
    }) 
    .filter((i) => i) as Number[]); 

キャスティング以外の方法がありますか?

環境:strictNullChecksを有効にしたTSC2.1。

+0

あなたはどのタイプのタイスクリプトですか?あなたの初期コードはTS 2.0.9で修正なしで私にとってうまく動作します – Paarth

+0

この問題は--strictNullChecksと仮定しています – artem

+2

この問題は部分的に[どのように型ガードが配列上のフィルターに伝播されず、代わりにReadonlyArraysだけでhttps://github.com/Microsoft/TypeScript/pull/10916)。 – y2bd

答えて

2

組み込みのfilter関数では、受信するのとまったく同じ型の配列を返すと宣言しています。

しかし、配列とuser-defined type guard functionを受け入れ、独自の完全型セーフフィルタ関数を定義し、異なる型の配列を返すことができます。

どのように便利わからないが、ここでは、次のとおりです。

function typeFilter<T, R extends T>(a: T[], f: (e: T) => e is R): R[] { 
    const r: R[] = []; 
    a.forEach(e => { if (f(e)) r.push(e) }); 
    return r; 
} 

それがこのように使用することができます:

const arry = [1, 2, 3, 4, "5", 6]; 

function isNumber(e): e is number { 
    return typeof e === 'number'; 
} 

const numArry: number[] = typeFilter(arry, isNumber); 

残念ながら、isNumber()があるため別の、明示的に型指定された関数として定義する必要がありますコンパイラはインライン関数e => typeof e === 'number'も型ガードであることを認識するほどスマートではありません。

2

map(...)関数シグネチャは次のとおりです。あなたのケースでは

map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; 

、ジェネリック型Uは次のようになります。number | undefined

filter(...)シグネチャは次のとおりです。

filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[];   

Tが来ているので、配列インタフェースの署名(Array<T>)から、 n型は同じ型のvalue引数(ジェネリック型T)の配列になります。あなたのケースではnumber | undefined

戻り値の型はnumber | undefinedです。

これに基づいて、キャスト式を使用する必要があります。この動作を望まない場合は、--strictNullChecksフラグを削除できます。

+0

@Diulleiありがとうございました。組み込み関数の元の型定義をチェックするのは非常に参考になり、本当に素晴らしい提案です。 – shuntksh

+0

私はあなたを助けてうれしい! – Diullei

関連する問題