Note: Arrays are also sometimes used as tuples in JavaScript, these are
annotated differently in Flow. See the Tuple docs for more information.
Arrays are a special list-like type of object in JavaScript. You can create
arrays a couple different ways.
1
2
3
|
new Array(1, 2, 3);
new Array(3);
[1, 2, 3];
|
{"value":"new Array(1, 2, 3); // [1, 2, 3];\nnew Array(3); // [undefined, undefined, undefined]\n[1, 2, 3]; // [1, 2, 3];\n","tokens":[{"type":"T_NEW","context":"normal","value":"new","line":1,"start":0,"end":3},{"type":"T_IDENTIFIER","context":"normal","value":"Array","line":1,"start":4,"end":9},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":9,"end":10},{"type":"T_NUMBER","context":"normal","value":"1","line":1,"start":10,"end":11},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":11,"end":12},{"type":"T_NUMBER","context":"normal","value":"2","line":1,"start":13,"end":14},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":14,"end":15},{"type":"T_NUMBER","context":"normal","value":"3","line":1,"start":16,"end":17},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":17,"end":18},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":18,"end":19},{"type":"Line","context":"comment","value":"// [1, 2, 3];","line":1,"start":20,"end":33},{"type":"T_NEW","context":"normal","value":"new","line":2,"start":34,"end":37},{"type":"T_IDENTIFIER","context":"normal","value":"Array","line":2,"start":38,"end":43},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":43,"end":44},{"type":"T_NUMBER","context":"normal","value":"3","line":2,"start":44,"end":45},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":45,"end":46},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":46,"end":47},{"type":"Line","context":"comment","value":"// [undefined, undefined, undefined]","line":2,"start":54,"end":90},{"type":"T_LBRACKET","context":"normal","value":"[","line":3,"start":91,"end":92},{"type":"T_NUMBER","context":"normal","value":"1","line":3,"start":92,"end":93},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":93,"end":94},{"type":"T_NUMBER","context":"normal","value":"2","line":3,"start":95,"end":96},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":96,"end":97},{"type":"T_NUMBER","context":"normal","value":"3","line":3,"start":98,"end":99},{"type":"T_RBRACKET","context":"normal","value":"]","line":3,"start":99,"end":100},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":100,"end":101},{"type":"Line","context":"comment","value":"// [1, 2, 3];","line":3,"start":111,"end":124}],"errors":[]}
You can also create arrays and add values to them later on:
1
2
3
4
|
let arr = [];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
|
{"value":"let arr = []; // []\narr[0] = 1; // [1]\narr[1] = 2; // [1, 2]\narr[2] = 3; // [1, 2, 3]\n","tokens":[{"type":"T_LET","context":"normal","value":"let","line":1,"start":0,"end":3},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":1,"start":4,"end":7},{"type":"T_ASSIGN","context":"normal","value":"=","line":1,"start":8,"end":9},{"type":"T_LBRACKET","context":"normal","value":"[","line":1,"start":10,"end":11},{"type":"T_RBRACKET","context":"normal","value":"]","line":1,"start":11,"end":12},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":12,"end":13},{"type":"Line","context":"comment","value":"// []","line":1,"start":14,"end":19},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":2,"start":20,"end":23},{"type":"T_LBRACKET","context":"normal","value":"[","line":2,"start":23,"end":24},{"type":"T_NUMBER","context":"normal","value":"0","line":2,"start":24,"end":25},{"type":"T_RBRACKET","context":"normal","value":"]","line":2,"start":25,"end":26},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":27,"end":28},{"type":"T_NUMBER","context":"normal","value":"1","line":2,"start":29,"end":30},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":30,"end":31},{"type":"Line","context":"comment","value":"// [1]","line":2,"start":34,"end":40},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":3,"start":41,"end":44},{"type":"T_LBRACKET","context":"normal","value":"[","line":3,"start":44,"end":45},{"type":"T_NUMBER","context":"normal","value":"1","line":3,"start":45,"end":46},{"type":"T_RBRACKET","context":"normal","value":"]","line":3,"start":46,"end":47},{"type":"T_ASSIGN","context":"normal","value":"=","line":3,"start":48,"end":49},{"type":"T_NUMBER","context":"normal","value":"2","line":3,"start":50,"end":51},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":51,"end":52},{"type":"Line","context":"comment","value":"// [1, 2]","line":3,"start":55,"end":64},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":4,"start":65,"end":68},{"type":"T_LBRACKET","context":"normal","value":"[","line":4,"start":68,"end":69},{"type":"T_NUMBER","context":"normal","value":"2","line":4,"start":69,"end":70},{"type":"T_RBRACKET","context":"normal","value":"]","line":4,"start":70,"end":71},{"type":"T_ASSIGN","context":"normal","value":"=","line":4,"start":72,"end":73},{"type":"T_NUMBER","context":"normal","value":"3","line":4,"start":74,"end":75},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":75,"end":76},{"type":"Line","context":"comment","value":"// [1, 2, 3]","line":4,"start":79,"end":91}],"errors":[]}
Array
Type
To create an array type you can use Array<Type>
type where Type
is the type
of elements in the array. For example, to create a type for an array of numbers
you use Array<number>
.
1
|
let arr: Array<number> = [1, 2, 3];
|
{"value":"let arr: Array<number> = [1, 2, 3];\n","tokens":[{"type":"T_LET","context":"normal","value":"let","line":1,"start":0,"end":3},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":1,"start":4,"end":7},{"type":"T_COLON","context":"type","value":":","line":1,"start":7,"end":8},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":1,"start":9,"end":14},{"type":"T_LESS_THAN","context":"type","value":"<","line":1,"start":14,"end":15},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":15,"end":21},{"type":"T_GREATER_THAN","context":"type","value":">","line":1,"start":21,"end":22},{"type":"T_ASSIGN","context":"normal","value":"=","line":1,"start":23,"end":24},{"type":"T_LBRACKET","context":"normal","value":"[","line":1,"start":25,"end":26},{"type":"T_NUMBER","context":"normal","value":"1","line":1,"start":26,"end":27},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":27,"end":28},{"type":"T_NUMBER","context":"normal","value":"2","line":1,"start":29,"end":30},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":30,"end":31},{"type":"T_NUMBER","context":"normal","value":"3","line":1,"start":32,"end":33},{"type":"T_RBRACKET","context":"normal","value":"]","line":1,"start":33,"end":34},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":34,"end":35}],"errors":[]}
You can put any type within Array<Type>
.
1
2
3
|
let arr1: Array<boolean> = [true, false, true];
let arr2: Array<string> = ["A", "B", "C"];
let arr3: Array<mixed> = [1, true, "three"]
|
{"value":"let arr1: Array<boolean> = [true, false, true];\nlet arr2: Array<string> = [\"A\", \"B\", \"C\"];\nlet arr3: Array<mixed> = [1, true, \"three\"]\n","tokens":[{"type":"T_LET","context":"normal","value":"let","line":1,"start":0,"end":3},{"type":"T_IDENTIFIER","context":"normal","value":"arr1","line":1,"start":4,"end":8},{"type":"T_COLON","context":"type","value":":","line":1,"start":8,"end":9},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":1,"start":10,"end":15},{"type":"T_LESS_THAN","context":"type","value":"<","line":1,"start":15,"end":16},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":1,"start":16,"end":23},{"type":"T_GREATER_THAN","context":"type","value":">","line":1,"start":23,"end":24},{"type":"T_ASSIGN","context":"normal","value":"=","line":1,"start":25,"end":26},{"type":"T_LBRACKET","context":"normal","value":"[","line":1,"start":27,"end":28},{"type":"T_TRUE","context":"normal","value":"true","line":1,"start":28,"end":32},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":32,"end":33},{"type":"T_FALSE","context":"normal","value":"false","line":1,"start":34,"end":39},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":39,"end":40},{"type":"T_TRUE","context":"normal","value":"true","line":1,"start":41,"end":45},{"type":"T_RBRACKET","context":"normal","value":"]","line":1,"start":45,"end":46},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":46,"end":47},{"type":"T_LET","context":"normal","value":"let","line":2,"start":48,"end":51},{"type":"T_IDENTIFIER","context":"normal","value":"arr2","line":2,"start":52,"end":56},{"type":"T_COLON","context":"type","value":":","line":2,"start":56,"end":57},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":2,"start":58,"end":63},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":63,"end":64},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":64,"end":70},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":70,"end":71},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":72,"end":73},{"type":"T_LBRACKET","context":"normal","value":"[","line":2,"start":74,"end":75},{"type":"T_STRING","context":"normal","value":"\"A\"","line":2,"start":75,"end":78},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":78,"end":79},{"type":"T_STRING","context":"normal","value":"\"B\"","line":2,"start":80,"end":83},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":83,"end":84},{"type":"T_STRING","context":"normal","value":"\"C\"","line":2,"start":85,"end":88},{"type":"T_RBRACKET","context":"normal","value":"]","line":2,"start":88,"end":89},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":89,"end":90},{"type":"T_LET","context":"normal","value":"let","line":3,"start":91,"end":94},{"type":"T_IDENTIFIER","context":"normal","value":"arr3","line":3,"start":95,"end":99},{"type":"T_COLON","context":"type","value":":","line":3,"start":99,"end":100},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":3,"start":101,"end":106},{"type":"T_LESS_THAN","context":"type","value":"<","line":3,"start":106,"end":107},{"type":"T_MIXED_TYPE","context":"type","value":"mixed","line":3,"start":107,"end":112},{"type":"T_GREATER_THAN","context":"type","value":">","line":3,"start":112,"end":113},{"type":"T_ASSIGN","context":"normal","value":"=","line":3,"start":114,"end":115},{"type":"T_LBRACKET","context":"normal","value":"[","line":3,"start":116,"end":117},{"type":"T_NUMBER","context":"normal","value":"1","line":3,"start":117,"end":118},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":118,"end":119},{"type":"T_TRUE","context":"normal","value":"true","line":3,"start":120,"end":124},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":124,"end":125},{"type":"T_STRING","context":"normal","value":"\"three\"","line":3,"start":126,"end":133},{"type":"T_RBRACKET","context":"normal","value":"]","line":3,"start":133,"end":134}],"errors":[]}
Array
Type Shorthand Syntax
There’s also a slightly shorter form of this syntax: Type[]
.
1
|
let arr: number[] = [0, 1, 2, 3];
|
{"value":"let arr: number[] = [0, 1, 2, 3];\n","tokens":[{"type":"T_LET","context":"normal","value":"let","line":1,"start":0,"end":3},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":1,"start":4,"end":7},{"type":"T_COLON","context":"type","value":":","line":1,"start":7,"end":8},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":9,"end":15},{"type":"T_LBRACKET","context":"type","value":"[","line":1,"start":15,"end":16},{"type":"T_RBRACKET","context":"type","value":"]","line":1,"start":16,"end":17},{"type":"T_ASSIGN","context":"normal","value":"=","line":1,"start":18,"end":19},{"type":"T_LBRACKET","context":"normal","value":"[","line":1,"start":20,"end":21},{"type":"T_NUMBER","context":"normal","value":"0","line":1,"start":21,"end":22},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":22,"end":23},{"type":"T_NUMBER","context":"normal","value":"1","line":1,"start":24,"end":25},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":25,"end":26},{"type":"T_NUMBER","context":"normal","value":"2","line":1,"start":27,"end":28},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":28,"end":29},{"type":"T_NUMBER","context":"normal","value":"3","line":1,"start":30,"end":31},{"type":"T_RBRACKET","context":"normal","value":"]","line":1,"start":31,"end":32},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":32,"end":33}],"errors":[]}
Just note that ?Type[]
is the equivalent of ?Array<T>
and not Array<?T>
.
1
2
3
4
|
let arr1: ?number[] = null;
let arr2: ?number[] = [1, 2];
let arr3: ?number[] = [null];
|
Cannot assign array literal to `arr3` because null [1] is incompatible with number [2] in array element. [incompatible-type]
{"value":"// @flow\nlet arr1: ?number[] = null; // Works!\nlet arr2: ?number[] = [1, 2]; // Works!\nlet arr3: ?number[] = [null]; // Error!\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_LET","context":"normal","value":"let","line":2,"start":9,"end":12},{"type":"T_IDENTIFIER","context":"normal","value":"arr1","line":2,"start":13,"end":17},{"type":"T_COLON","context":"type","value":":","line":2,"start":17,"end":18},{"type":"T_PLING","context":"type","value":"?","line":2,"start":19,"end":20},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":20,"end":26},{"type":"T_LBRACKET","context":"type","value":"[","line":2,"start":26,"end":27},{"type":"T_RBRACKET","context":"type","value":"]","line":2,"start":27,"end":28},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":29,"end":30},{"type":"T_NULL","context":"normal","value":"null","line":2,"start":31,"end":35},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":35,"end":36},{"type":"Line","context":"comment","value":"// Works!","line":2,"start":39,"end":48},{"type":"T_LET","context":"normal","value":"let","line":3,"start":49,"end":52},{"type":"T_IDENTIFIER","context":"normal","value":"arr2","line":3,"start":53,"end":57},{"type":"T_COLON","context":"type","value":":","line":3,"start":57,"end":58},{"type":"T_PLING","context":"type","value":"?","line":3,"start":59,"end":60},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":3,"start":60,"end":66},{"type":"T_LBRACKET","context":"type","value":"[","line":3,"start":66,"end":67},{"type":"T_RBRACKET","context":"type","value":"]","line":3,"start":67,"end":68},{"type":"T_ASSIGN","context":"normal","value":"=","line":3,"start":69,"end":70},{"type":"T_LBRACKET","context":"normal","value":"[","line":3,"start":71,"end":72},{"type":"T_NUMBER","context":"normal","value":"1","line":3,"start":72,"end":73},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":73,"end":74},{"type":"T_NUMBER","context":"normal","value":"2","line":3,"start":75,"end":76},{"type":"T_RBRACKET","context":"normal","value":"]","line":3,"start":76,"end":77},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":77,"end":78},{"type":"Line","context":"comment","value":"// Works!","line":3,"start":79,"end":88},{"type":"T_LET","context":"normal","value":"let","line":4,"start":89,"end":92},{"type":"T_IDENTIFIER","context":"normal","value":"arr3","line":4,"start":93,"end":97},{"type":"T_COLON","context":"type","value":":","line":4,"start":97,"end":98},{"type":"T_PLING","context":"type","value":"?","line":4,"start":99,"end":100},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":4,"start":100,"end":106},{"type":"T_LBRACKET","context":"type","value":"[","line":4,"start":106,"end":107},{"type":"T_RBRACKET","context":"type","value":"]","line":4,"start":107,"end":108},{"type":"T_ASSIGN","context":"normal","value":"=","line":4,"start":109,"end":110},{"type":"T_LBRACKET","context":"normal","value":"[","line":4,"start":111,"end":112},{"type":"T_NULL","context":"normal","value":"null","line":4,"start":112,"end":116},{"type":"T_RBRACKET","context":"normal","value":"]","line":4,"start":116,"end":117},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":117,"end":118},{"type":"Line","context":"comment","value":"// Error!","line":4,"start":119,"end":128}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot assign array literal to `arr3` because null [1] is incompatible with number [2] in array element. [incompatible-type]","context":"let arr3: ?number[] = [null]; // Error!","source":"-","start":{"line":4,"column":24,"offset":112},"end":{"line":4,"column":27,"offset":116}}],"operation":null}]}
If you want to make it Array<?T>
you can use parenthesis like: (?Type)[]
1
2
3
4
|
let arr1: (?number)[] = null;
let arr2: (?number)[] = [1, 2];
let arr3: (?number)[] = [null];
|
Cannot assign `null` to `arr1` because null [1] is incompatible with array type [2]. [incompatible-type]
{"value":"// @flow\nlet arr1: (?number)[] = null; // Error!\nlet arr2: (?number)[] = [1, 2]; // Works!\nlet arr3: (?number)[] = [null]; // Works!\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_LET","context":"normal","value":"let","line":2,"start":9,"end":12},{"type":"T_IDENTIFIER","context":"normal","value":"arr1","line":2,"start":13,"end":17},{"type":"T_COLON","context":"type","value":":","line":2,"start":17,"end":18},{"type":"T_LPAREN","context":"type","value":"(","line":2,"start":19,"end":20},{"type":"T_PLING","context":"type","value":"?","line":2,"start":20,"end":21},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":21,"end":27},{"type":"T_RPAREN","context":"type","value":")","line":2,"start":27,"end":28},{"type":"T_LBRACKET","context":"type","value":"[","line":2,"start":28,"end":29},{"type":"T_RBRACKET","context":"type","value":"]","line":2,"start":29,"end":30},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":31,"end":32},{"type":"T_NULL","context":"normal","value":"null","line":2,"start":33,"end":37},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":37,"end":38},{"type":"Line","context":"comment","value":"// Error!","line":2,"start":41,"end":50},{"type":"T_LET","context":"normal","value":"let","line":3,"start":51,"end":54},{"type":"T_IDENTIFIER","context":"normal","value":"arr2","line":3,"start":55,"end":59},{"type":"T_COLON","context":"type","value":":","line":3,"start":59,"end":60},{"type":"T_LPAREN","context":"type","value":"(","line":3,"start":61,"end":62},{"type":"T_PLING","context":"type","value":"?","line":3,"start":62,"end":63},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":3,"start":63,"end":69},{"type":"T_RPAREN","context":"type","value":")","line":3,"start":69,"end":70},{"type":"T_LBRACKET","context":"type","value":"[","line":3,"start":70,"end":71},{"type":"T_RBRACKET","context":"type","value":"]","line":3,"start":71,"end":72},{"type":"T_ASSIGN","context":"normal","value":"=","line":3,"start":73,"end":74},{"type":"T_LBRACKET","context":"normal","value":"[","line":3,"start":75,"end":76},{"type":"T_NUMBER","context":"normal","value":"1","line":3,"start":76,"end":77},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":77,"end":78},{"type":"T_NUMBER","context":"normal","value":"2","line":3,"start":79,"end":80},{"type":"T_RBRACKET","context":"normal","value":"]","line":3,"start":80,"end":81},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":81,"end":82},{"type":"Line","context":"comment","value":"// Works!","line":3,"start":83,"end":92},{"type":"T_LET","context":"normal","value":"let","line":4,"start":93,"end":96},{"type":"T_IDENTIFIER","context":"normal","value":"arr3","line":4,"start":97,"end":101},{"type":"T_COLON","context":"type","value":":","line":4,"start":101,"end":102},{"type":"T_LPAREN","context":"type","value":"(","line":4,"start":103,"end":104},{"type":"T_PLING","context":"type","value":"?","line":4,"start":104,"end":105},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":4,"start":105,"end":111},{"type":"T_RPAREN","context":"type","value":")","line":4,"start":111,"end":112},{"type":"T_LBRACKET","context":"type","value":"[","line":4,"start":112,"end":113},{"type":"T_RBRACKET","context":"type","value":"]","line":4,"start":113,"end":114},{"type":"T_ASSIGN","context":"normal","value":"=","line":4,"start":115,"end":116},{"type":"T_LBRACKET","context":"normal","value":"[","line":4,"start":117,"end":118},{"type":"T_NULL","context":"normal","value":"null","line":4,"start":118,"end":122},{"type":"T_RBRACKET","context":"normal","value":"]","line":4,"start":122,"end":123},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":123,"end":124},{"type":"Line","context":"comment","value":"// Works!","line":4,"start":125,"end":134}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot assign `null` to `arr1` because null [1] is incompatible with array type [2]. [incompatible-type]","context":"let arr1: (?number)[] = null; // Error!","source":"-","start":{"line":2,"column":25,"offset":33},"end":{"line":2,"column":28,"offset":37}}],"operation":null}]}
Array access is unsafe
When you retrieve an element from an array there is always a possibility that
it is undefined
. You could have either accessed an index which is out of the
bounds of the array, or the element could not exist because it is a “sparse
array”.
For example, you could be accessing an element that is out of the bounds of the
array.
1
2
3
4
|
let array: Array<number> = [0, 1, 2];
let value: number = array[3];
|
{"value":"// @flow\nlet array: Array<number> = [0, 1, 2];\nlet value: number = array[3]; // Works.\n // ^ undefined\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_LET","context":"normal","value":"let","line":2,"start":9,"end":12},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":2,"start":13,"end":18},{"type":"T_COLON","context":"type","value":":","line":2,"start":18,"end":19},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":2,"start":20,"end":25},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":25,"end":26},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":26,"end":32},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":32,"end":33},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":34,"end":35},{"type":"T_LBRACKET","context":"normal","value":"[","line":2,"start":36,"end":37},{"type":"T_NUMBER","context":"normal","value":"0","line":2,"start":37,"end":38},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":38,"end":39},{"type":"T_NUMBER","context":"normal","value":"1","line":2,"start":40,"end":41},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":41,"end":42},{"type":"T_NUMBER","context":"normal","value":"2","line":2,"start":43,"end":44},{"type":"T_RBRACKET","context":"normal","value":"]","line":2,"start":44,"end":45},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":45,"end":46},{"type":"T_LET","context":"normal","value":"let","line":3,"start":47,"end":50},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":3,"start":51,"end":56},{"type":"T_COLON","context":"type","value":":","line":3,"start":56,"end":57},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":3,"start":58,"end":64},{"type":"T_ASSIGN","context":"normal","value":"=","line":3,"start":65,"end":66},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":3,"start":67,"end":72},{"type":"T_LBRACKET","context":"normal","value":"[","line":3,"start":72,"end":73},{"type":"T_NUMBER","context":"normal","value":"3","line":3,"start":73,"end":74},{"type":"T_RBRACKET","context":"normal","value":"]","line":3,"start":74,"end":75},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":75,"end":76},{"type":"Line","context":"comment","value":"// Works.","line":3,"start":77,"end":86},{"type":"Line","context":"comment","value":"// ^ undefined","line":4,"start":110,"end":124}],"errors":[]}
Or you could be accessing an element that does not exist if it is a “sparse
array”.
1
2
3
4
5
6
7
8
|
let array: Array<number> = [];
array[0] = 0;
array[2] = 2;
let value: number = array[1];
|
{"value":"// @flow\nlet array: Array<number> = [];\n\narray[0] = 0;\narray[2] = 2;\n\nlet value: number = array[1]; // Works.\n // ^ undefined\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_LET","context":"normal","value":"let","line":2,"start":9,"end":12},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":2,"start":13,"end":18},{"type":"T_COLON","context":"type","value":":","line":2,"start":18,"end":19},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":2,"start":20,"end":25},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":25,"end":26},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":26,"end":32},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":32,"end":33},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":34,"end":35},{"type":"T_LBRACKET","context":"normal","value":"[","line":2,"start":36,"end":37},{"type":"T_RBRACKET","context":"normal","value":"]","line":2,"start":37,"end":38},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":38,"end":39},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":4,"start":41,"end":46},{"type":"T_LBRACKET","context":"normal","value":"[","line":4,"start":46,"end":47},{"type":"T_NUMBER","context":"normal","value":"0","line":4,"start":47,"end":48},{"type":"T_RBRACKET","context":"normal","value":"]","line":4,"start":48,"end":49},{"type":"T_ASSIGN","context":"normal","value":"=","line":4,"start":50,"end":51},{"type":"T_NUMBER","context":"normal","value":"0","line":4,"start":52,"end":53},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":53,"end":54},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":5,"start":55,"end":60},{"type":"T_LBRACKET","context":"normal","value":"[","line":5,"start":60,"end":61},{"type":"T_NUMBER","context":"normal","value":"2","line":5,"start":61,"end":62},{"type":"T_RBRACKET","context":"normal","value":"]","line":5,"start":62,"end":63},{"type":"T_ASSIGN","context":"normal","value":"=","line":5,"start":64,"end":65},{"type":"T_NUMBER","context":"normal","value":"2","line":5,"start":66,"end":67},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":67,"end":68},{"type":"T_LET","context":"normal","value":"let","line":7,"start":70,"end":73},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":7,"start":74,"end":79},{"type":"T_COLON","context":"type","value":":","line":7,"start":79,"end":80},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":7,"start":81,"end":87},{"type":"T_ASSIGN","context":"normal","value":"=","line":7,"start":88,"end":89},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":7,"start":90,"end":95},{"type":"T_LBRACKET","context":"normal","value":"[","line":7,"start":95,"end":96},{"type":"T_NUMBER","context":"normal","value":"1","line":7,"start":96,"end":97},{"type":"T_RBRACKET","context":"normal","value":"]","line":7,"start":97,"end":98},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":98,"end":99},{"type":"Line","context":"comment","value":"// Works.","line":7,"start":100,"end":109},{"type":"Line","context":"comment","value":"// ^ undefined","line":8,"start":133,"end":147}],"errors":[]}
In order to make this safe, Flow would have to mark every single array access
as “possibly undefined”.
Flow does not do this because it would be extremely inconvenient to use. You
would be forced to refine the type of every value you get when accessing an
array.
1
2
3
4
5
6
|
let array: Array<number> = [0, 1, 2];
let value: number | void = array[1];
if (value !== undefined) {
}
|
{"value":"let array: Array<number> = [0, 1, 2];\nlet value: number | void = array[1];\n\nif (value !== undefined) {\n // number\n}\n","tokens":[{"type":"T_LET","context":"normal","value":"let","line":1,"start":0,"end":3},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":1,"start":4,"end":9},{"type":"T_COLON","context":"type","value":":","line":1,"start":9,"end":10},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":1,"start":11,"end":16},{"type":"T_LESS_THAN","context":"type","value":"<","line":1,"start":16,"end":17},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":17,"end":23},{"type":"T_GREATER_THAN","context":"type","value":">","line":1,"start":23,"end":24},{"type":"T_ASSIGN","context":"normal","value":"=","line":1,"start":25,"end":26},{"type":"T_LBRACKET","context":"normal","value":"[","line":1,"start":27,"end":28},{"type":"T_NUMBER","context":"normal","value":"0","line":1,"start":28,"end":29},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":29,"end":30},{"type":"T_NUMBER","context":"normal","value":"1","line":1,"start":31,"end":32},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":32,"end":33},{"type":"T_NUMBER","context":"normal","value":"2","line":1,"start":34,"end":35},{"type":"T_RBRACKET","context":"normal","value":"]","line":1,"start":35,"end":36},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":36,"end":37},{"type":"T_LET","context":"normal","value":"let","line":2,"start":38,"end":41},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":2,"start":42,"end":47},{"type":"T_COLON","context":"type","value":":","line":2,"start":47,"end":48},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":49,"end":55},{"type":"T_BIT_OR","context":"type","value":"|","line":2,"start":56,"end":57},{"type":"T_VOID_TYPE","context":"type","value":"void","line":2,"start":58,"end":62},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":63,"end":64},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":2,"start":65,"end":70},{"type":"T_LBRACKET","context":"normal","value":"[","line":2,"start":70,"end":71},{"type":"T_NUMBER","context":"normal","value":"1","line":2,"start":71,"end":72},{"type":"T_RBRACKET","context":"normal","value":"]","line":2,"start":72,"end":73},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":73,"end":74},{"type":"T_IF","context":"normal","value":"if","line":4,"start":76,"end":78},{"type":"T_LPAREN","context":"normal","value":"(","line":4,"start":79,"end":80},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":4,"start":80,"end":85},{"type":"T_STRICT_NOT_EQUAL","context":"normal","value":"!==","line":4,"start":86,"end":89},{"type":"T_IDENTIFIER","context":"normal","value":"undefined","line":4,"start":90,"end":99},{"type":"T_RPAREN","context":"normal","value":")","line":4,"start":99,"end":100},{"type":"T_LCURLY","context":"normal","value":"{","line":4,"start":101,"end":102},{"type":"Line","context":"comment","value":"// number","line":5,"start":105,"end":114},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":115,"end":116}],"errors":[]}
As Flow is made to be smarter it may be possible in the future to fix this
problem, but for now you should be aware of it.
$ReadOnlyArray<T>
Similar to $ReadOnly<T>
, it is the supertype
of all arrays and all tuples and represents a read-only view of an array. It does
not contain any methods that will allow an object of this type to be mutated
(no push()
, pop()
, etc.).
1
2
3
4
5
6
|
const readonlyArray: $ReadOnlyArray<number> = [1, 2, 3]
const first = readonlyArray[0]
readonlyArray[1] = 20
readonlyArray.push(4)
|
Cannot assign `20` to `readonlyArray[1]` because read-only arrays cannot be written to. [cannot-write]
Cannot call `readonlyArray.push` because property `push` is missing in `$ReadOnlyArray` [1]. [prop-missing]
{"value":"// @flow\nconst readonlyArray: $ReadOnlyArray<number> = [1, 2, 3]\n\nconst first = readonlyArray[0] // OK to read\nreadonlyArray[1] = 20 // Error!\nreadonlyArray.push(4) // Error!\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_CONST","context":"normal","value":"const","line":2,"start":9,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"readonlyArray","line":2,"start":15,"end":28},{"type":"T_COLON","context":"type","value":":","line":2,"start":28,"end":29},{"type":"T_IDENTIFIER","context":"type","value":"$ReadOnlyArray","line":2,"start":30,"end":44},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":44,"end":45},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":45,"end":51},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":51,"end":52},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":53,"end":54},{"type":"T_LBRACKET","context":"normal","value":"[","line":2,"start":55,"end":56},{"type":"T_NUMBER","context":"normal","value":"1","line":2,"start":56,"end":57},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":57,"end":58},{"type":"T_NUMBER","context":"normal","value":"2","line":2,"start":59,"end":60},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":60,"end":61},{"type":"T_NUMBER","context":"normal","value":"3","line":2,"start":62,"end":63},{"type":"T_RBRACKET","context":"normal","value":"]","line":2,"start":63,"end":64},{"type":"T_CONST","context":"normal","value":"const","line":4,"start":66,"end":71},{"type":"T_IDENTIFIER","context":"normal","value":"first","line":4,"start":72,"end":77},{"type":"T_ASSIGN","context":"normal","value":"=","line":4,"start":78,"end":79},{"type":"T_IDENTIFIER","context":"normal","value":"readonlyArray","line":4,"start":80,"end":93},{"type":"T_LBRACKET","context":"normal","value":"[","line":4,"start":93,"end":94},{"type":"T_NUMBER","context":"normal","value":"0","line":4,"start":94,"end":95},{"type":"T_RBRACKET","context":"normal","value":"]","line":4,"start":95,"end":96},{"type":"Line","context":"comment","value":"// OK to read","line":4,"start":97,"end":110},{"type":"T_IDENTIFIER","context":"normal","value":"readonlyArray","line":5,"start":111,"end":124},{"type":"T_LBRACKET","context":"normal","value":"[","line":5,"start":124,"end":125},{"type":"T_NUMBER","context":"normal","value":"1","line":5,"start":125,"end":126},{"type":"T_RBRACKET","context":"normal","value":"]","line":5,"start":126,"end":127},{"type":"T_ASSIGN","context":"normal","value":"=","line":5,"start":128,"end":129},{"type":"T_NUMBER","context":"normal","value":"20","line":5,"start":130,"end":132},{"type":"Line","context":"comment","value":"// Error!","line":5,"start":142,"end":151},{"type":"T_IDENTIFIER","context":"normal","value":"readonlyArray","line":6,"start":152,"end":165},{"type":"T_PERIOD","context":"normal","value":".","line":6,"start":165,"end":166},{"type":"T_IDENTIFIER","context":"normal","value":"push","line":6,"start":166,"end":170},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":170,"end":171},{"type":"T_NUMBER","context":"normal","value":"4","line":6,"start":171,"end":172},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":172,"end":173},{"type":"Line","context":"comment","value":"// Error!","line":6,"start":183,"end":192}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot assign `20` to `readonlyArray[1]` because read-only arrays cannot be written to. [cannot-write]","context":"readonlyArray[1] = 20 // Error!","source":"-","start":{"line":5,"column":1,"offset":111},"end":{"line":5,"column":16,"offset":127}}],"operation":null},{"id":"E2","messages":[{"id":"E2M1","description":"Cannot call `readonlyArray.push` because property `push` is missing in `$ReadOnlyArray` [1]. [prop-missing]","context":"readonlyArray.push(4) // Error!","source":"-","start":{"line":6,"column":15,"offset":166},"end":{"line":6,"column":18,"offset":170}}],"operation":null}]}
Note that an array of type $ReadOnlyArray<T>
can still have mutable elements:
1
2
3
4
|
const readonlyArray: $ReadOnlyArray<{x: number}> = [{x: 1}];
readonlyArray[0] = {x: 42};
readonlyArray[0].x = 42;
|
Cannot assign object literal to `readonlyArray[0]` because read-only arrays cannot be written to. [cannot-write]
{"value":"// @flow\nconst readonlyArray: $ReadOnlyArray<{x: number}> = [{x: 1}];\nreadonlyArray[0] = {x: 42}; // Error!\nreadonlyArray[0].x = 42; // OK\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_CONST","context":"normal","value":"const","line":2,"start":9,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"readonlyArray","line":2,"start":15,"end":28},{"type":"T_COLON","context":"type","value":":","line":2,"start":28,"end":29},{"type":"T_IDENTIFIER","context":"type","value":"$ReadOnlyArray","line":2,"start":30,"end":44},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":44,"end":45},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":45,"end":46},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":2,"start":46,"end":47},{"type":"T_COLON","context":"type","value":":","line":2,"start":47,"end":48},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":49,"end":55},{"type":"T_RCURLY","context":"type","value":"}","line":2,"start":55,"end":56},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":56,"end":57},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":58,"end":59},{"type":"T_LBRACKET","context":"normal","value":"[","line":2,"start":60,"end":61},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":61,"end":62},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":2,"start":62,"end":63},{"type":"T_COLON","context":"normal","value":":","line":2,"start":63,"end":64},{"type":"T_NUMBER","context":"normal","value":"1","line":2,"start":65,"end":66},{"type":"T_RCURLY","context":"normal","value":"}","line":2,"start":66,"end":67},{"type":"T_RBRACKET","context":"normal","value":"]","line":2,"start":67,"end":68},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":68,"end":69},{"type":"T_IDENTIFIER","context":"normal","value":"readonlyArray","line":3,"start":70,"end":83},{"type":"T_LBRACKET","context":"normal","value":"[","line":3,"start":83,"end":84},{"type":"T_NUMBER","context":"normal","value":"0","line":3,"start":84,"end":85},{"type":"T_RBRACKET","context":"normal","value":"]","line":3,"start":85,"end":86},{"type":"T_ASSIGN","context":"normal","value":"=","line":3,"start":87,"end":88},{"type":"T_LCURLY","context":"normal","value":"{","line":3,"start":89,"end":90},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":3,"start":90,"end":91},{"type":"T_COLON","context":"normal","value":":","line":3,"start":91,"end":92},{"type":"T_NUMBER","context":"normal","value":"42","line":3,"start":93,"end":95},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":95,"end":96},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":96,"end":97},{"type":"Line","context":"comment","value":"// Error!","line":3,"start":98,"end":107},{"type":"T_IDENTIFIER","context":"normal","value":"readonlyArray","line":4,"start":108,"end":121},{"type":"T_LBRACKET","context":"normal","value":"[","line":4,"start":121,"end":122},{"type":"T_NUMBER","context":"normal","value":"0","line":4,"start":122,"end":123},{"type":"T_RBRACKET","context":"normal","value":"]","line":4,"start":123,"end":124},{"type":"T_PERIOD","context":"normal","value":".","line":4,"start":124,"end":125},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":4,"start":125,"end":126},{"type":"T_ASSIGN","context":"normal","value":"=","line":4,"start":127,"end":128},{"type":"T_NUMBER","context":"normal","value":"42","line":4,"start":129,"end":131},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":131,"end":132},{"type":"Line","context":"comment","value":"// OK","line":4,"start":133,"end":138}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot assign object literal to `readonlyArray[0]` because read-only arrays cannot be written to. [cannot-write]","context":"readonlyArray[0] = {x: 42}; // Error!","source":"-","start":{"line":3,"column":1,"offset":70},"end":{"line":3,"column":16,"offset":86}}],"operation":null}]}
The main advantage to using $ReadOnlyArray
instead of Array
is that $ReadOnlyArray
’s
type parameter is covariant while Array
’s type parameter is invariant. That means that
$ReadOnlyArray<number>
is a subtype of $ReadOnlyArray<number | string>
while
Array<number>
is NOT a subtype of Array<number | string>
. So it’s often useful to use
$ReadOnlyArray
in type annotations for arrays of various types of elements.
Take, for instance, the following scenario:
1
2
3
4
5
6
7
|
const someOperation = (arr: Array<number | string>) => {
}
const array: Array<number> = [1]
someOperation(array)
|
Cannot call `someOperation` with `array` bound to `arr` because number [1] is incompatible with string [2] in array element. [incompatible-call]
{"value":"// @flow\nconst someOperation = (arr: Array<number | string>) => {\n // Here we could do `arr.push('a string')`\n}\n\nconst array: Array<number> = [1]\nsomeOperation(array) // Error!\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_CONST","context":"normal","value":"const","line":2,"start":9,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"someOperation","line":2,"start":15,"end":28},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":29,"end":30},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":31,"end":32},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":2,"start":32,"end":35},{"type":"T_COLON","context":"type","value":":","line":2,"start":35,"end":36},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":2,"start":37,"end":42},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":42,"end":43},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":43,"end":49},{"type":"T_BIT_OR","context":"type","value":"|","line":2,"start":50,"end":51},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":52,"end":58},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":58,"end":59},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":59,"end":60},{"type":"T_ARROW","context":"normal","value":"=>","line":2,"start":61,"end":63},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":64,"end":65},{"type":"Line","context":"comment","value":"// Here we could do `arr.push('a string')`","line":3,"start":68,"end":110},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":111,"end":112},{"type":"T_CONST","context":"normal","value":"const","line":6,"start":114,"end":119},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":6,"start":120,"end":125},{"type":"T_COLON","context":"type","value":":","line":6,"start":125,"end":126},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":6,"start":127,"end":132},{"type":"T_LESS_THAN","context":"type","value":"<","line":6,"start":132,"end":133},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":6,"start":133,"end":139},{"type":"T_GREATER_THAN","context":"type","value":">","line":6,"start":139,"end":140},{"type":"T_ASSIGN","context":"normal","value":"=","line":6,"start":141,"end":142},{"type":"T_LBRACKET","context":"normal","value":"[","line":6,"start":143,"end":144},{"type":"T_NUMBER","context":"normal","value":"1","line":6,"start":144,"end":145},{"type":"T_RBRACKET","context":"normal","value":"]","line":6,"start":145,"end":146},{"type":"T_IDENTIFIER","context":"normal","value":"someOperation","line":7,"start":147,"end":160},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":160,"end":161},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":7,"start":161,"end":166},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":166,"end":167},{"type":"Line","context":"comment","value":"// Error!","line":7,"start":168,"end":177}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot call `someOperation` with `array` bound to `arr` because number [1] is incompatible with string [2] in array element. [incompatible-call]","context":"someOperation(array) // Error!","source":"-","start":{"line":7,"column":15,"offset":161},"end":{"line":7,"column":19,"offset":166}}],"operation":null}]}
Since the parameter arr
of the someOperation
function is typed as a mutable
Array
, pushing a string into it would be possible inside that scope, which
would then break the type contract of the outside array
variable. By
annotating the parameter as $ReadOnlyArray
instead in this case, Flow can be
sure this won’t happen and no errors will occur:
1
2
3
4
5
6
7
|
const someOperation = (arr: $ReadOnlyArray<number | string>) => {
}
const array: Array<number> = [1]
someOperation(array)
|
{"value":"// @flow\nconst someOperation = (arr: $ReadOnlyArray<number | string>) => {\n // Nothing can be added to `arr`\n}\n\nconst array: Array<number> = [1]\nsomeOperation(array) // Works!\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_CONST","context":"normal","value":"const","line":2,"start":9,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"someOperation","line":2,"start":15,"end":28},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":29,"end":30},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":31,"end":32},{"type":"T_IDENTIFIER","context":"normal","value":"arr","line":2,"start":32,"end":35},{"type":"T_COLON","context":"type","value":":","line":2,"start":35,"end":36},{"type":"T_IDENTIFIER","context":"type","value":"$ReadOnlyArray","line":2,"start":37,"end":51},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":51,"end":52},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":52,"end":58},{"type":"T_BIT_OR","context":"type","value":"|","line":2,"start":59,"end":60},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":61,"end":67},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":67,"end":68},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":68,"end":69},{"type":"T_ARROW","context":"normal","value":"=>","line":2,"start":70,"end":72},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":73,"end":74},{"type":"Line","context":"comment","value":"// Nothing can be added to `arr`","line":3,"start":77,"end":109},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":110,"end":111},{"type":"T_CONST","context":"normal","value":"const","line":6,"start":113,"end":118},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":6,"start":119,"end":124},{"type":"T_COLON","context":"type","value":":","line":6,"start":124,"end":125},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":6,"start":126,"end":131},{"type":"T_LESS_THAN","context":"type","value":"<","line":6,"start":131,"end":132},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":6,"start":132,"end":138},{"type":"T_GREATER_THAN","context":"type","value":">","line":6,"start":138,"end":139},{"type":"T_ASSIGN","context":"normal","value":"=","line":6,"start":140,"end":141},{"type":"T_LBRACKET","context":"normal","value":"[","line":6,"start":142,"end":143},{"type":"T_NUMBER","context":"normal","value":"1","line":6,"start":143,"end":144},{"type":"T_RBRACKET","context":"normal","value":"]","line":6,"start":144,"end":145},{"type":"T_IDENTIFIER","context":"normal","value":"someOperation","line":7,"start":146,"end":159},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":159,"end":160},{"type":"T_IDENTIFIER","context":"normal","value":"array","line":7,"start":160,"end":165},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":165,"end":166},{"type":"Line","context":"comment","value":"// Works!","line":7,"start":167,"end":176}],"errors":[]}