web-dev-qa-db-ja.com

TypeScriptで、配列の型を定義します。最初の要素は他の要素よりも具体的です

最初の要素が特定の型(関数など)であり、残りの要素が空の型である配列の型を定義したいと思います。例えば:

type FAs = [Function, {}, {}, {}, ...]; // pseudo code

そのようなことは可能ですか?

目的は、次のような単一引数関数を提供することです。

const myCaller = ([fun, ...args]: FAs) => fun.apply(args);

別の方法は、次のようにmyCallerに2つの引数を使用することです。

const myCaller = (fun: Function, args: any[]) => fun.apply(args);

しかし、審美的な理由から、私は単一の引数を使用することを好みます。また、型システムがおそらく任意の長さのタプルであるものをサポートしているかどうかも疑問に思います。多分そのようなことは、私が理解していないコンピュータサイエンスの理由から望ましくないでしょう。

24
anticrisis

定義すると

type FAs = [Function, {}];

次に、タイプFAsの値には、タイプFunctionの最初のエレメント、タイプ{}の2番目のエレメント、およびFunction | {}の後続のエレメントが必要です。 TypeScriptのリテラル配列型はこのように機能します。 TS docs から:

既知のインデックスのセット外の要素にアクセスする場合、代わりに共用体タイプが使用されます。

これは、3番目の要素としてFunction型の値を渡すことができるため、を除くすべてのことを行う必要があります配列の等。しかし、実際にはFunction{}と互換性があるため、とにかくそうなります。

これを回避する方法はありません。 TSには、最初のn要素が特定のタイプである配列タイプを定義する方法がなく、他の特定の特定のタイプの残りの要素が任意の数ありますタイプ。

また、型システムがおそらく任意の長さのタプルであるものをサポートしているかどうかも疑問に思います。

実際、型システムonlyは任意の長さのタプルをサポートします。あなたが言うなら

type Tuple = [number, number];

このタイプは、数値を含む長さ2以上の任意の配列と互換性があります。あなたが言うなら

type Tuple = [string, number];

このタイプは、長さが2またはそれ以上で、最初の要素として文字列、2番目の要素として数値、およびいずれかの配列と互換性があります。 3番目の文字列または数値など。この動作の理由を「コンピュータサイエンスベース」とは呼びません。 TSがチェックできることの問題です。

代替アプローチ

interface Arglist {
  [index: number]: object;
  0: Function;
}

const a1: Arglist = [func];
const a2: Arglist = [22];                  // fails
const a3: Arglist = [func, "foo"];         // fails
const a4: Arglist = [func, obj];
const a5: Arglist = [func, obj, obj];
17
user663031

TypeScriptの現在のバージョンでは、配列スプレッドを使用してこれを行うことができます。

type FAs = [Function, ...Array<{}>]

1からnまでの長さをサポートします(最初の要素は必須です)。

21
juusaw

TypeScript 2.3でこれができる最高の方法だと思います。このようなタイプは、たとえばlodashで見ることができます。

interface IMyCaller {
  <R>([fn]: [() => R]): R;
  <R,A>([fn, a]: [(a: A) => R, A]): R;
  <R,A,B>([fn, a, b]: [(a: A, b: B) => R, A, B]): R;
  <R,A,B,C>([fn, a, b, c]: [(a: A, b: B, c: C) => R, A, B, C]): R;
  // keep adding these until you get tired
}

const myCaller: IMyCaller = ([fun, ...args]) => fun.apply(args);
0
dbandstra