Adding type annotations is an important part of your interaction with Flow.
Flow has a powerful ability to infer the types of your programs. The majority
of your code can rely on it. Still, there are places where you’ll want to add
types.
Imagine the following concat
function for concatenating two strings together.
1
2
3
|
function concat(a, b) {
return a + b;
}
|
{"value":"function concat(a, b) {\n return a + b;\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":1,"start":16,"end":17},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":17,"end":18},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":1,"start":19,"end":20},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":20,"end":21},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":22,"end":23},{"type":"T_RETURN","context":"normal","value":"return","line":2,"start":26,"end":32},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":2,"start":33,"end":34},{"type":"T_PLUS","context":"normal","value":"+","line":2,"start":35,"end":36},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":37,"end":38},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":38,"end":39},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":40,"end":41}],"errors":[]}
When you use this function, Flow knows exactly what is going on.
{"value":"concat(\"A\", \"B\"); // Works!\n","tokens":[{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":1,"start":0,"end":6},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":6,"end":7},{"type":"T_STRING","context":"normal","value":"\"A\"","line":1,"start":7,"end":10},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":10,"end":11},{"type":"T_STRING","context":"normal","value":"\"B\"","line":1,"start":12,"end":15},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":15,"end":16},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":16,"end":17},{"type":"Line","context":"comment","value":"// Works!","line":1,"start":18,"end":27}],"errors":[]}
However, you can use the +
operator on strings or numbers, so this would also
be valid.
{"value":"concat(1, 2); // Works!\n","tokens":[{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":1,"start":0,"end":6},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":6,"end":7},{"type":"T_NUMBER","context":"normal","value":"1","line":1,"start":7,"end":8},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":8,"end":9},{"type":"T_NUMBER","context":"normal","value":"2","line":1,"start":10,"end":11},{"type":"T_RPAREN","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":"// Works!","line":1,"start":14,"end":23}],"errors":[]}
But suppose you only want to allow strings in your function. For that you can
add types.
1
2
3
|
function concat(a: string, b: string) {
return a + b;
}
|
{"value":"function concat(a: string, b: string) {\n return a + b;\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":1,"start":16,"end":17},{"type":"T_COLON","context":"type","value":":","line":1,"start":17,"end":18},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":19,"end":25},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":25,"end":26},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":1,"start":27,"end":28},{"type":"T_COLON","context":"type","value":":","line":1,"start":28,"end":29},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":30,"end":36},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":36,"end":37},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":38,"end":39},{"type":"T_RETURN","context":"normal","value":"return","line":2,"start":42,"end":48},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":2,"start":49,"end":50},{"type":"T_PLUS","context":"normal","value":"+","line":2,"start":51,"end":52},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":53,"end":54},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":54,"end":55},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":56,"end":57}],"errors":[]}
Now you’ll get a warning from Flow if you try to use numbers.
1
2
3
4
5
6
7
|
function concat(a: string, b: string) {
return a + b;
}
concat("A", "B");
concat(1, 2);
|
Cannot call `concat` with `1` bound to `a` because number [1] is incompatible with string [2]. [incompatible-call]
Cannot call `concat` with `2` bound to `b` because number [1] is incompatible with string [2]. [incompatible-call]
{"value":"// @flow\nfunction concat(a: string, b: string) {\n return a + b;\n}\n\nconcat(\"A\", \"B\"); // Works!\nconcat(1, 2); // Error!\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_FUNCTION","context":"normal","value":"function","line":2,"start":9,"end":17},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":2,"start":18,"end":24},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":24,"end":25},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":2,"start":25,"end":26},{"type":"T_COLON","context":"type","value":":","line":2,"start":26,"end":27},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":28,"end":34},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":34,"end":35},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":36,"end":37},{"type":"T_COLON","context":"type","value":":","line":2,"start":37,"end":38},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":39,"end":45},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":45,"end":46},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":47,"end":48},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":51,"end":57},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":3,"start":58,"end":59},{"type":"T_PLUS","context":"normal","value":"+","line":3,"start":60,"end":61},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":3,"start":62,"end":63},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":63,"end":64},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":65,"end":66},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":6,"start":68,"end":74},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":74,"end":75},{"type":"T_STRING","context":"normal","value":"\"A\"","line":6,"start":75,"end":78},{"type":"T_COMMA","context":"normal","value":",","line":6,"start":78,"end":79},{"type":"T_STRING","context":"normal","value":"\"B\"","line":6,"start":80,"end":83},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":83,"end":84},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":84,"end":85},{"type":"Line","context":"comment","value":"// Works!","line":6,"start":86,"end":95},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":7,"start":96,"end":102},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":102,"end":103},{"type":"T_NUMBER","context":"normal","value":"1","line":7,"start":103,"end":104},{"type":"T_COMMA","context":"normal","value":",","line":7,"start":104,"end":105},{"type":"T_NUMBER","context":"normal","value":"2","line":7,"start":106,"end":107},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":107,"end":108},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":108,"end":109},{"type":"Line","context":"comment","value":"// Error!","line":7,"start":110,"end":119}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot call `concat` with `1` bound to `a` because number [1] is incompatible with string [2]. [incompatible-call]","context":"concat(1, 2); // Error!","source":"-","start":{"line":7,"column":8,"offset":103},"end":{"line":7,"column":8,"offset":104}}],"operation":null},{"id":"E2","messages":[{"id":"E2M1","description":"Cannot call `concat` with `2` bound to `b` because number [1] is incompatible with string [2]. [incompatible-call]","context":"concat(1, 2); // Error!","source":"-","start":{"line":7,"column":11,"offset":106},"end":{"line":7,"column":11,"offset":107}}],"operation":null}]}
Setting up “boundaries” with your types means you can tell Flow your intent on
top of the inference it already does.
This guide will teach you the syntax and semantics of all the different types
you can have in Flow.