TypeScript: how to declare array of fixed size for type checking at Compile Time

前端 未结 3 1313
生来不讨喜
生来不讨喜 2021-01-17 10:19

Update: These checks are meant for compile time, not at runtime. In my example, the failed cases are all caught at compile

相关标签:
3条回答
  • 2021-01-17 10:57

    From Typescript: Can I define an n-length tuple type?, programmatically, with dynamic length:

    type Tuple<TItem, TLength extends number> = [TItem, ...TItem[]] & { length: TLength };
    
    type Tuple9<T> = Tuple<T, 9>;
    
    0 讨论(0)
  • 2021-01-17 11:18

    Here is a simple example of a class to control the length of its internal array. It isn't fool-proof (when getting/setting you may want to consider whether you are shallow/deep cloning etc:

    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 讨论(0)
  • 2021-01-17 11:20

    Update 2: From version 3.4, what the OP asked for is now fully possible with a succinct syntax (Playground link):

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

    Update 1: From version 2.7, TypeScript can now distinguish between lists of different sizes.

    I don't think it's possible to type-check the length of a tuple. Here's the opinion of TypeScript's author on this subject.

    I'd argue that what you're asking for is not necessary. Suppose you define this type

    type StringTriplet = [string, string, string]
    

    and define a variable of that type:

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

    You can't get more variables out of that triplet e.g.

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

    will give an error whereas this doesn't as expected:

    const [one, two, three] = a;
    

    The only situation where I think the lack of ability to constrain the length becomes a problem is e.g. when you map over the triplet

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

    and expect that result have 3 elements when in fact it can have more than 3. However, in this case, you are treating a as a collection instead of a tuple anyway so that's not a correct use case for the tuple syntax.

    0 讨论(0)
提交回复
热议问题