web-dev-qa-db-ja.com

TypeScript:コンパイル時に型チェックのために固定サイズの配列を宣言する方法

pdate:これらのチェックはコンパイル時ではなく、runtimeを対象としています。私の例では、失敗したケースはすべてコンパイル時にキャッチされ、他のshould-failケースでも同様の動作が期待されます。

クラスのすべてのメンバーを同じ長さの配列にしたいテーブルのようなクラスを書いているとしましょう。

class MyClass {
  tableHead:  string[3]; // expect to be a 3 element array of strings
  tableCells: number[3]; // expect to be a 3 element array of numbers
}

これまでに見つけた最も近い解決策は次のとおりです。

class MyClass {
  tableHead:  [string, string, string];
  tableCells: [number, number, number];
}

let bar = new MyClass();
bar.tableHead = ['a', 'b', 'c']; // pass
bar.tableHead = ['a', 'b'];      // fail
bar.tableHead = ['a', 'b', 1];   // fail

// BUT these also pass, which are expected to fail at compile time
bar.tableHead = ['a', 'b', 'c', 'd', 'e']; // pass
bar.Push('d'); // pass
bar.Push('e'); // pass

より良いアイデアはありますか?

10
benjaminz

更新2:バージョン3.4から、OPが要求したことは、簡潔な構文( Playground link )で完全に可能になりました。

class MyClass {
  tableHead: readonly [string, string, string]
  tableCells: readonly [number, number, number]
}

更新1:バージョン2.7以降、TypeScriptで サイズの異なるリストを区別 できるようになりました。

タプルの長さをタイプチェックすることは不可能だと思います。 ここ は、この主題に関するTypeScriptの著者の意見です。

あなたが求めていることは必要ではないと私は主張します。このタイプを定義するとします

type StringTriplet = [string, string, string]

そのタイプの変数を定義します:

const a: StringTriplet = ['a', 'b', 'c']

あなたはそのトリプレットからより多くの変数を取得することはできません。

const [one, two, three, four] = a;

これは期待どおりではありませんが、エラーが発生します。

const [one, two, three] = a;

長さを制約する能力の欠如が問題になると私が思う唯一の状況は、例えばトリプレットを超えてmap

const result = a.map(/* some pure function */)

そして、実際にはresultに3つ以上の要素がある可能性があることを期待します。ただし、この場合はaをタプルではなくコレクションとして扱っているため、正しくありません。タプル構文の使用例。

11
Huy Nguyen

From TypeScript:n-length Tuple typeを定義できますか? 、動的な長さでプログラム的に:

type Tuple<TItem, TLength extends number> = [TItem, ...TItem[]] & { length: TLength };

type Tuple9<T> = Tuple<T, 9>;
2
cancerbero

内部配列の長さを制御するクラスの簡単な例を次に示します。それは絶対確実ではありません(取得/設定時に、浅い/深いクローンであるかどうかなどを検討する必要があります):

https://jsfiddle.net/904d9jhc/

class ControlledArray {

  constructor(num) {
    this.a = Array(num).fill(0); // Creates new array and fills it with zeros
  }

  set(arr) {
    if (!(arr instanceof Array) || arr.length != this.a.length) {
      return false;
    }
    this.a = arr.slice();
    return true;
  }

  get() {
    return this.a.slice();
  }

}

$( document ).ready(function($) {

  var m = new ControlledArray(3);

  alert(m.set('vera')); // fail
  alert(m.set(['vera', 'chuck', 'dave'])); // pass

  alert(m.get()); // gets copy of controlled array

});
0
Chris Cousins