Functions have two places where types are applied: Parameters (input) and the
return value (output).
1
2
3
4
5
6
7
8
|
function concat(a: string, b: string): string {
return a + b;
}
concat("foo", "bar");
concat(true, false);
|
Cannot call `concat` with `true` bound to `a` because boolean [1] is incompatible with string [2]. [incompatible-call]
Cannot call `concat` with `false` bound to `b` because boolean [1] is incompatible with string [2]. [incompatible-call]
{"value":"// @flow\nfunction concat(a: string, b: string): string {\n return a + b;\n}\n\nconcat(\"foo\", \"bar\"); // Works!\n// $ExpectError\nconcat(true, false); // 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_COLON","context":"type","value":":","line":2,"start":46,"end":47},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":48,"end":54},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":55,"end":56},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":59,"end":65},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":3,"start":66,"end":67},{"type":"T_PLUS","context":"normal","value":"+","line":3,"start":68,"end":69},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":3,"start":70,"end":71},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":71,"end":72},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":73,"end":74},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":6,"start":76,"end":82},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":82,"end":83},{"type":"T_STRING","context":"normal","value":"\"foo\"","line":6,"start":83,"end":88},{"type":"T_COMMA","context":"normal","value":",","line":6,"start":88,"end":89},{"type":"T_STRING","context":"normal","value":"\"bar\"","line":6,"start":90,"end":95},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":95,"end":96},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":96,"end":97},{"type":"Line","context":"comment","value":"// Works!","line":6,"start":98,"end":107},{"type":"Line","context":"comment","value":"// $ExpectError","line":7,"start":108,"end":123},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":8,"start":124,"end":130},{"type":"T_LPAREN","context":"normal","value":"(","line":8,"start":130,"end":131},{"type":"T_TRUE","context":"normal","value":"true","line":8,"start":131,"end":135},{"type":"T_COMMA","context":"normal","value":",","line":8,"start":135,"end":136},{"type":"T_FALSE","context":"normal","value":"false","line":8,"start":137,"end":142},{"type":"T_RPAREN","context":"normal","value":")","line":8,"start":142,"end":143},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":143,"end":144},{"type":"Line","context":"comment","value":"// Error!","line":8,"start":146,"end":155}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot call `concat` with `true` bound to `a` because boolean [1] is incompatible with string [2]. [incompatible-call]","context":"concat(true, false); // Error!","source":"-","start":{"line":8,"column":8,"offset":131},"end":{"line":8,"column":11,"offset":135}}],"operation":null},{"id":"E2","messages":[{"id":"E2M1","description":"Cannot call `concat` with `false` bound to `b` because boolean [1] is incompatible with string [2]. [incompatible-call]","context":"concat(true, false); // Error!","source":"-","start":{"line":8,"column":14,"offset":137},"end":{"line":8,"column":18,"offset":142}}],"operation":null}]}
Using inference, these types are often optional:
1
2
3
4
5
6
7
8
|
function concat(a, b) {
return a + b;
}
concat("foo", "bar");
concat(true, false);
|
Cannot add `a` and `b` because boolean [1] is incompatible with string [2]. [incompatible-type]
Cannot add `a` and `b` because boolean [1] is incompatible with string [2]. [incompatible-type]
{"value":"// @flow\nfunction concat(a, b) {\n return a + b;\n}\n\nconcat(\"foo\", \"bar\"); // Works!\n// $ExpectError\nconcat(true, false); // 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_COMMA","context":"normal","value":",","line":2,"start":26,"end":27},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":28,"end":29},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":29,"end":30},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":31,"end":32},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":35,"end":41},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":3,"start":42,"end":43},{"type":"T_PLUS","context":"normal","value":"+","line":3,"start":44,"end":45},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":3,"start":46,"end":47},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":47,"end":48},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":49,"end":50},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":6,"start":52,"end":58},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":58,"end":59},{"type":"T_STRING","context":"normal","value":"\"foo\"","line":6,"start":59,"end":64},{"type":"T_COMMA","context":"normal","value":",","line":6,"start":64,"end":65},{"type":"T_STRING","context":"normal","value":"\"bar\"","line":6,"start":66,"end":71},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":71,"end":72},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":72,"end":73},{"type":"Line","context":"comment","value":"// Works!","line":6,"start":74,"end":83},{"type":"Line","context":"comment","value":"// $ExpectError","line":7,"start":84,"end":99},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":8,"start":100,"end":106},{"type":"T_LPAREN","context":"normal","value":"(","line":8,"start":106,"end":107},{"type":"T_TRUE","context":"normal","value":"true","line":8,"start":107,"end":111},{"type":"T_COMMA","context":"normal","value":",","line":8,"start":111,"end":112},{"type":"T_FALSE","context":"normal","value":"false","line":8,"start":113,"end":118},{"type":"T_RPAREN","context":"normal","value":")","line":8,"start":118,"end":119},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":119,"end":120},{"type":"Line","context":"comment","value":"// Error!","line":8,"start":122,"end":131}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot add `a` and `b` because boolean [1] is incompatible with string [2]. [incompatible-type]","context":" return a + b;","source":"-","start":{"line":3,"column":10,"offset":42},"end":{"line":3,"column":10,"offset":43}}],"operation":null},{"id":"E2","messages":[{"id":"E2M1","description":"Cannot add `a` and `b` because boolean [1] is incompatible with string [2]. [incompatible-type]","context":" return a + b;","source":"-","start":{"line":3,"column":14,"offset":46},"end":{"line":3,"column":14,"offset":47}}],"operation":null}]}
Sometimes Flow’s inference will create types that are more permissive than you
want them to be.
1
2
3
4
5
6
7
|
function concat(a, b) {
return a + b;
}
concat("foo", "bar");
concat(1, 2);
|
{"value":"// @flow\nfunction concat(a, b) {\n return a + b;\n}\n\nconcat(\"foo\", \"bar\"); // Works!\nconcat(1, 2); // Works!\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_COMMA","context":"normal","value":",","line":2,"start":26,"end":27},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":28,"end":29},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":29,"end":30},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":31,"end":32},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":35,"end":41},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":3,"start":42,"end":43},{"type":"T_PLUS","context":"normal","value":"+","line":3,"start":44,"end":45},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":3,"start":46,"end":47},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":47,"end":48},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":49,"end":50},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":6,"start":52,"end":58},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":58,"end":59},{"type":"T_STRING","context":"normal","value":"\"foo\"","line":6,"start":59,"end":64},{"type":"T_COMMA","context":"normal","value":",","line":6,"start":64,"end":65},{"type":"T_STRING","context":"normal","value":"\"bar\"","line":6,"start":66,"end":71},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":71,"end":72},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":72,"end":73},{"type":"Line","context":"comment","value":"// Works!","line":6,"start":74,"end":83},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":7,"start":84,"end":90},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":90,"end":91},{"type":"T_NUMBER","context":"normal","value":"1","line":7,"start":91,"end":92},{"type":"T_COMMA","context":"normal","value":",","line":7,"start":92,"end":93},{"type":"T_NUMBER","context":"normal","value":"2","line":7,"start":94,"end":95},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":95,"end":96},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":96,"end":97},{"type":"Line","context":"comment","value":"// Works!","line":7,"start":106,"end":115}],"errors":[]}
For that reason (and others), it’s useful to write types for important
functions.
Syntax of functions
There are three forms of functions that each have their own slightly different syntax.
Function Declarations
Here you can see the syntax for function declarations with and without types
added.
1
2
3
4
5
6
7
|
function method(str, bool, ...nums) {
}
function method(str: string, bool?: boolean, ...nums: Array<number>): void {
}
|
{"value":"function method(str, bool, ...nums) {\n // ...\n}\n\nfunction method(str: string, bool?: boolean, ...nums: Array<number>): void {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"str","line":1,"start":16,"end":19},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":19,"end":20},{"type":"T_IDENTIFIER","context":"normal","value":"bool","line":1,"start":21,"end":25},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":25,"end":26},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":1,"start":27,"end":30},{"type":"T_IDENTIFIER","context":"normal","value":"nums","line":1,"start":30,"end":34},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":34,"end":35},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":36,"end":37},{"type":"Line","context":"comment","value":"// ...","line":2,"start":40,"end":46},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":47,"end":48},{"type":"T_FUNCTION","context":"normal","value":"function","line":5,"start":50,"end":58},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":5,"start":59,"end":65},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":65,"end":66},{"type":"T_IDENTIFIER","context":"normal","value":"str","line":5,"start":66,"end":69},{"type":"T_COLON","context":"type","value":":","line":5,"start":69,"end":70},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":71,"end":77},{"type":"T_COMMA","context":"normal","value":",","line":5,"start":77,"end":78},{"type":"T_IDENTIFIER","context":"normal","value":"bool","line":5,"start":79,"end":83},{"type":"T_PLING","context":"normal","value":"?","line":5,"start":83,"end":84},{"type":"T_COLON","context":"type","value":":","line":5,"start":84,"end":85},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":5,"start":86,"end":93},{"type":"T_COMMA","context":"normal","value":",","line":5,"start":93,"end":94},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":5,"start":95,"end":98},{"type":"T_IDENTIFIER","context":"normal","value":"nums","line":5,"start":98,"end":102},{"type":"T_COLON","context":"type","value":":","line":5,"start":102,"end":103},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":5,"start":104,"end":109},{"type":"T_LESS_THAN","context":"type","value":"<","line":5,"start":109,"end":110},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":5,"start":110,"end":116},{"type":"T_GREATER_THAN","context":"type","value":">","line":5,"start":116,"end":117},{"type":"T_RPAREN","context":"normal","value":")","line":5,"start":117,"end":118},{"type":"T_COLON","context":"type","value":":","line":5,"start":118,"end":119},{"type":"T_VOID_TYPE","context":"type","value":"void","line":5,"start":120,"end":124},{"type":"T_LCURLY","context":"normal","value":"{","line":5,"start":125,"end":126},{"type":"Line","context":"comment","value":"// ...","line":6,"start":129,"end":135},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":136,"end":137}],"errors":[]}
Arrow Functions
Here you can see the syntax for arrow functions with and without types added.
1
2
3
4
5
6
7
|
let method = (str, bool, ...nums) => {
};
let method = (str: string, bool?: boolean, ...nums: Array<number>): void => {
};
|
{"value":"let method = (str, bool, ...nums) => {\n // ...\n};\n\nlet method = (str: string, bool?: boolean, ...nums: Array<number>): void => {\n // ...\n};\n","tokens":[{"type":"T_LET","context":"normal","value":"let","line":1,"start":0,"end":3},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":4,"end":10},{"type":"T_ASSIGN","context":"normal","value":"=","line":1,"start":11,"end":12},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":13,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"str","line":1,"start":14,"end":17},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":17,"end":18},{"type":"T_IDENTIFIER","context":"normal","value":"bool","line":1,"start":19,"end":23},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":23,"end":24},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":1,"start":25,"end":28},{"type":"T_IDENTIFIER","context":"normal","value":"nums","line":1,"start":28,"end":32},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":32,"end":33},{"type":"T_ARROW","context":"normal","value":"=>","line":1,"start":34,"end":36},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":37,"end":38},{"type":"Line","context":"comment","value":"// ...","line":2,"start":41,"end":47},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":48,"end":49},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":49,"end":50},{"type":"T_LET","context":"normal","value":"let","line":5,"start":52,"end":55},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":5,"start":56,"end":62},{"type":"T_ASSIGN","context":"normal","value":"=","line":5,"start":63,"end":64},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":65,"end":66},{"type":"T_IDENTIFIER","context":"normal","value":"str","line":5,"start":66,"end":69},{"type":"T_COLON","context":"type","value":":","line":5,"start":69,"end":70},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":71,"end":77},{"type":"T_COMMA","context":"normal","value":",","line":5,"start":77,"end":78},{"type":"T_IDENTIFIER","context":"normal","value":"bool","line":5,"start":79,"end":83},{"type":"T_PLING","context":"normal","value":"?","line":5,"start":83,"end":84},{"type":"T_COLON","context":"type","value":":","line":5,"start":84,"end":85},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":5,"start":86,"end":93},{"type":"T_COMMA","context":"normal","value":",","line":5,"start":93,"end":94},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":5,"start":95,"end":98},{"type":"T_IDENTIFIER","context":"normal","value":"nums","line":5,"start":98,"end":102},{"type":"T_COLON","context":"type","value":":","line":5,"start":102,"end":103},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":5,"start":104,"end":109},{"type":"T_LESS_THAN","context":"type","value":"<","line":5,"start":109,"end":110},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":5,"start":110,"end":116},{"type":"T_GREATER_THAN","context":"type","value":">","line":5,"start":116,"end":117},{"type":"T_RPAREN","context":"normal","value":")","line":5,"start":117,"end":118},{"type":"T_COLON","context":"type","value":":","line":5,"start":118,"end":119},{"type":"T_VOID_TYPE","context":"type","value":"void","line":5,"start":120,"end":124},{"type":"T_ARROW","context":"normal","value":"=>","line":5,"start":125,"end":127},{"type":"T_LCURLY","context":"normal","value":"{","line":5,"start":128,"end":129},{"type":"Line","context":"comment","value":"// ...","line":6,"start":132,"end":138},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":139,"end":140},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":140,"end":141}],"errors":[]}
Function Types
Here you can see the syntax for writing types that are functions.
1
|
(str: string, bool?: boolean, ...nums: Array<number>) => void
|
{"value":"(str: string, bool?: boolean, ...nums: Array<number>) => void\n","tokens":[{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":0,"end":1},{"type":"T_IDENTIFIER","context":"normal","value":"str","line":1,"start":1,"end":4},{"type":"T_COLON","context":"type","value":":","line":1,"start":4,"end":5},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":6,"end":12},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":12,"end":13},{"type":"T_IDENTIFIER","context":"normal","value":"bool","line":1,"start":14,"end":18},{"type":"T_PLING","context":"normal","value":"?","line":1,"start":18,"end":19},{"type":"T_COLON","context":"type","value":":","line":1,"start":19,"end":20},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":1,"start":21,"end":28},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":28,"end":29},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":1,"start":30,"end":33},{"type":"T_IDENTIFIER","context":"normal","value":"nums","line":1,"start":33,"end":37},{"type":"T_COLON","context":"type","value":":","line":1,"start":37,"end":38},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":1,"start":39,"end":44},{"type":"T_LESS_THAN","context":"type","value":"<","line":1,"start":44,"end":45},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":45,"end":51},{"type":"T_GREATER_THAN","context":"type","value":">","line":1,"start":51,"end":52},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":52,"end":53},{"type":"T_ARROW","context":"normal","value":"=>","line":1,"start":54,"end":56},{"type":"T_VOID","context":"normal","value":"void","line":1,"start":57,"end":61}],"errors":[]}
You may also optionally leave out the parameter names.
1
|
(string, boolean | void, Array<number>) => void
|
{"value":"(string, boolean | void, Array<number>) => void\n","tokens":[{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":0,"end":1},{"type":"T_IDENTIFIER","context":"normal","value":"string","line":1,"start":1,"end":7},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":7,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"boolean","line":1,"start":9,"end":16},{"type":"T_BIT_OR","context":"normal","value":"|","line":1,"start":17,"end":18},{"type":"T_VOID","context":"normal","value":"void","line":1,"start":19,"end":23},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":23,"end":24},{"type":"T_IDENTIFIER","context":"normal","value":"Array","line":1,"start":25,"end":30},{"type":"T_LESS_THAN","context":"normal","value":"<","line":1,"start":30,"end":31},{"type":"T_IDENTIFIER","context":"normal","value":"number","line":1,"start":31,"end":37},{"type":"T_GREATER_THAN","context":"normal","value":">","line":1,"start":37,"end":38},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":38,"end":39},{"type":"T_ARROW","context":"normal","value":"=>","line":1,"start":40,"end":42},{"type":"T_VOID","context":"normal","value":"void","line":1,"start":43,"end":47}],"errors":[]}
You might use these functions types for something like a callback.
1
2
3
|
function method(callback: (error: Error | null, value: string | null) => void) {
}
|
{"value":"function method(callback: (error: Error | null, value: string | null) => void) {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"callback","line":1,"start":16,"end":24},{"type":"T_COLON","context":"type","value":":","line":1,"start":24,"end":25},{"type":"T_LPAREN","context":"type","value":"(","line":1,"start":26,"end":27},{"type":"T_IDENTIFIER","context":"normal","value":"error","line":1,"start":27,"end":32},{"type":"T_COLON","context":"type","value":":","line":1,"start":32,"end":33},{"type":"T_IDENTIFIER","context":"type","value":"Error","line":1,"start":34,"end":39},{"type":"T_BIT_OR","context":"type","value":"|","line":1,"start":40,"end":41},{"type":"T_NULL","context":"type","value":"null","line":1,"start":42,"end":46},{"type":"T_COMMA","context":"type","value":",","line":1,"start":46,"end":47},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":1,"start":48,"end":53},{"type":"T_COLON","context":"type","value":":","line":1,"start":53,"end":54},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":55,"end":61},{"type":"T_BIT_OR","context":"type","value":"|","line":1,"start":62,"end":63},{"type":"T_NULL","context":"type","value":"null","line":1,"start":64,"end":68},{"type":"T_RPAREN","context":"type","value":")","line":1,"start":68,"end":69},{"type":"T_ARROW","context":"type","value":"=>","line":1,"start":70,"end":72},{"type":"T_VOID_TYPE","context":"type","value":"void","line":1,"start":73,"end":77},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":77,"end":78},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":79,"end":80},{"type":"Line","context":"comment","value":"// ...","line":2,"start":83,"end":89},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":90,"end":91}],"errors":[]}
Function Parameters
Function parameters can have types by adding a colon :
followed by the type
after the name of the parameter.
1
2
3
|
function method(param1: string, param2: boolean) {
}
|
{"value":"function method(param1: string, param2: boolean) {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"param1","line":1,"start":16,"end":22},{"type":"T_COLON","context":"type","value":":","line":1,"start":22,"end":23},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":24,"end":30},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":30,"end":31},{"type":"T_IDENTIFIER","context":"normal","value":"param2","line":1,"start":32,"end":38},{"type":"T_COLON","context":"type","value":":","line":1,"start":38,"end":39},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":1,"start":40,"end":47},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":47,"end":48},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":49,"end":50},{"type":"Line","context":"comment","value":"// ...","line":2,"start":53,"end":59},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":60,"end":61}],"errors":[]}
Optional Parameters
You can also have optional parameters by adding a question mark ?
after the
name of the parameter and before the colon :
.
1
2
3
|
function method(optionalValue?: string) {
}
|
{"value":"function method(optionalValue?: string) {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"optionalValue","line":1,"start":16,"end":29},{"type":"T_PLING","context":"normal","value":"?","line":1,"start":29,"end":30},{"type":"T_COLON","context":"type","value":":","line":1,"start":30,"end":31},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":32,"end":38},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":38,"end":39},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":40,"end":41},{"type":"Line","context":"comment","value":"// ...","line":2,"start":44,"end":50},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":51,"end":52}],"errors":[]}
Optional parameters will accept missing, undefined
, or matching types. But
they will not accept null
.
1
2
3
4
5
6
7
8
9
10
|
function method(optionalValue?: string) {
}
method();
method(undefined);
method("string");
method(null);
|
Cannot call `method` with `null` bound to `optionalValue` because null [1] is incompatible with string [2]. [incompatible-call]
{"value":"// @flow\nfunction method(optionalValue?: string) {\n // ...\n}\n\nmethod(); // Works.\nmethod(undefined); // Works.\nmethod(\"string\"); // Works.\n// $ExpectError\nmethod(null); // 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":"method","line":2,"start":18,"end":24},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":24,"end":25},{"type":"T_IDENTIFIER","context":"normal","value":"optionalValue","line":2,"start":25,"end":38},{"type":"T_PLING","context":"normal","value":"?","line":2,"start":38,"end":39},{"type":"T_COLON","context":"type","value":":","line":2,"start":39,"end":40},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":41,"end":47},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":47,"end":48},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":49,"end":50},{"type":"Line","context":"comment","value":"// ...","line":3,"start":53,"end":59},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":60,"end":61},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":6,"start":63,"end":69},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":69,"end":70},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":70,"end":71},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":71,"end":72},{"type":"Line","context":"comment","value":"// Works.","line":6,"start":82,"end":91},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":7,"start":92,"end":98},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":98,"end":99},{"type":"T_IDENTIFIER","context":"normal","value":"undefined","line":7,"start":99,"end":108},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":108,"end":109},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":109,"end":110},{"type":"Line","context":"comment","value":"// Works.","line":7,"start":111,"end":120},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":8,"start":121,"end":127},{"type":"T_LPAREN","context":"normal","value":"(","line":8,"start":127,"end":128},{"type":"T_STRING","context":"normal","value":"\"string\"","line":8,"start":128,"end":136},{"type":"T_RPAREN","context":"normal","value":")","line":8,"start":136,"end":137},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":137,"end":138},{"type":"Line","context":"comment","value":"// Works.","line":8,"start":140,"end":149},{"type":"Line","context":"comment","value":"// $ExpectError","line":9,"start":150,"end":165},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":10,"start":166,"end":172},{"type":"T_LPAREN","context":"normal","value":"(","line":10,"start":172,"end":173},{"type":"T_NULL","context":"normal","value":"null","line":10,"start":173,"end":177},{"type":"T_RPAREN","context":"normal","value":")","line":10,"start":177,"end":178},{"type":"T_SEMICOLON","context":"normal","value":";","line":10,"start":178,"end":179},{"type":"Line","context":"comment","value":"// Error!","line":10,"start":185,"end":194}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot call `method` with `null` bound to `optionalValue` because null [1] is incompatible with string [2]. [incompatible-call]","context":"method(null); // Error!","source":"-","start":{"line":10,"column":8,"offset":173},"end":{"line":10,"column":11,"offset":177}}],"operation":null}]}
Rest Parameters
JavaScript also supports having rest parameters or parameters that collect an
array of arguments at the end of a list of parameters. These have an ellipsis
...
before them.
You can also add type annotations for rest parameters using the same syntax but
with an Array
.
1
2
3
|
function method(...args: Array<number>) {
}
|
{"value":"function method(...args: Array<number>) {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":1,"start":16,"end":19},{"type":"T_IDENTIFIER","context":"normal","value":"args","line":1,"start":19,"end":23},{"type":"T_COLON","context":"type","value":":","line":1,"start":23,"end":24},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":1,"start":25,"end":30},{"type":"T_LESS_THAN","context":"type","value":"<","line":1,"start":30,"end":31},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":31,"end":37},{"type":"T_GREATER_THAN","context":"type","value":">","line":1,"start":37,"end":38},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":38,"end":39},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":40,"end":41},{"type":"Line","context":"comment","value":"// ...","line":2,"start":44,"end":50},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":51,"end":52}],"errors":[]}
You can pass as many arguments as you want into a rest parameter.
1
2
3
4
5
6
7
8
9
|
function method(...args: Array<number>) {
}
method();
method(1);
method(1, 2);
method(1, 2, 3);
|
{"value":"// @flow\nfunction method(...args: Array<number>) {\n // ...\n}\n\nmethod(); // Works.\nmethod(1); // Works.\nmethod(1, 2); // Works.\nmethod(1, 2, 3); // Works.\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":"method","line":2,"start":18,"end":24},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":24,"end":25},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":2,"start":25,"end":28},{"type":"T_IDENTIFIER","context":"normal","value":"args","line":2,"start":28,"end":32},{"type":"T_COLON","context":"type","value":":","line":2,"start":32,"end":33},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":2,"start":34,"end":39},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":39,"end":40},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":40,"end":46},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":46,"end":47},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":47,"end":48},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":49,"end":50},{"type":"Line","context":"comment","value":"// ...","line":3,"start":53,"end":59},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":60,"end":61},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":6,"start":63,"end":69},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":69,"end":70},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":70,"end":71},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":71,"end":72},{"type":"Line","context":"comment","value":"// Works.","line":6,"start":80,"end":89},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":7,"start":90,"end":96},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":96,"end":97},{"type":"T_NUMBER","context":"normal","value":"1","line":7,"start":97,"end":98},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":98,"end":99},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":99,"end":100},{"type":"Line","context":"comment","value":"// Works.","line":7,"start":107,"end":116},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":8,"start":117,"end":123},{"type":"T_LPAREN","context":"normal","value":"(","line":8,"start":123,"end":124},{"type":"T_NUMBER","context":"normal","value":"1","line":8,"start":124,"end":125},{"type":"T_COMMA","context":"normal","value":",","line":8,"start":125,"end":126},{"type":"T_NUMBER","context":"normal","value":"2","line":8,"start":127,"end":128},{"type":"T_RPAREN","context":"normal","value":")","line":8,"start":128,"end":129},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":129,"end":130},{"type":"Line","context":"comment","value":"// Works.","line":8,"start":134,"end":143},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":9,"start":144,"end":150},{"type":"T_LPAREN","context":"normal","value":"(","line":9,"start":150,"end":151},{"type":"T_NUMBER","context":"normal","value":"1","line":9,"start":151,"end":152},{"type":"T_COMMA","context":"normal","value":",","line":9,"start":152,"end":153},{"type":"T_NUMBER","context":"normal","value":"2","line":9,"start":154,"end":155},{"type":"T_COMMA","context":"normal","value":",","line":9,"start":155,"end":156},{"type":"T_NUMBER","context":"normal","value":"3","line":9,"start":157,"end":158},{"type":"T_RPAREN","context":"normal","value":")","line":9,"start":158,"end":159},{"type":"T_SEMICOLON","context":"normal","value":";","line":9,"start":159,"end":160},{"type":"Line","context":"comment","value":"// Works.","line":9,"start":161,"end":170}],"errors":[]}
Note: If you add a type annotation to a rest parameter, it must always
explicitly be an Array
type.
Function Returns
Function returns can also add a type using a colon :
followed by the type
after the list of parameters.
1
2
3
|
function method(): number {
}
|
{"value":"function method(): number {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":16,"end":17},{"type":"T_COLON","context":"type","value":":","line":1,"start":17,"end":18},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":19,"end":25},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":26,"end":27},{"type":"Line","context":"comment","value":"// ...","line":2,"start":30,"end":36},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":37,"end":38}],"errors":[]}
Return types ensure that every branch of your function returns the same type.
This prevents you from accidentally not returning a value under certain
conditions.
1
2
3
4
5
6
7
|
function method(): boolean {
if (Math.random() > 0.5) {
return true;
}
}
|
Cannot expect boolean as the return type of function because boolean [1] is incompatible with implicitly-returned undefined. [incompatible-return]
{"value":"// @flow\n// $ExpectError\nfunction method(): boolean {\n if (Math.random() > 0.5) {\n return true;\n }\n}\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"Line","context":"comment","value":"// $ExpectError","line":2,"start":9,"end":24},{"type":"T_FUNCTION","context":"normal","value":"function","line":3,"start":25,"end":33},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":3,"start":34,"end":40},{"type":"T_LPAREN","context":"normal","value":"(","line":3,"start":40,"end":41},{"type":"T_RPAREN","context":"normal","value":")","line":3,"start":41,"end":42},{"type":"T_COLON","context":"type","value":":","line":3,"start":42,"end":43},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":3,"start":44,"end":51},{"type":"T_LCURLY","context":"normal","value":"{","line":3,"start":52,"end":53},{"type":"T_IF","context":"normal","value":"if","line":4,"start":56,"end":58},{"type":"T_LPAREN","context":"normal","value":"(","line":4,"start":59,"end":60},{"type":"T_IDENTIFIER","context":"normal","value":"Math","line":4,"start":60,"end":64},{"type":"T_PERIOD","context":"normal","value":".","line":4,"start":64,"end":65},{"type":"T_IDENTIFIER","context":"normal","value":"random","line":4,"start":65,"end":71},{"type":"T_LPAREN","context":"normal","value":"(","line":4,"start":71,"end":72},{"type":"T_RPAREN","context":"normal","value":")","line":4,"start":72,"end":73},{"type":"T_GREATER_THAN","context":"normal","value":">","line":4,"start":74,"end":75},{"type":"T_NUMBER","context":"normal","value":"0.5","line":4,"start":76,"end":79},{"type":"T_RPAREN","context":"normal","value":")","line":4,"start":79,"end":80},{"type":"T_LCURLY","context":"normal","value":"{","line":4,"start":81,"end":82},{"type":"T_RETURN","context":"normal","value":"return","line":5,"start":87,"end":93},{"type":"T_TRUE","context":"normal","value":"true","line":5,"start":94,"end":98},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":98,"end":99},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":102,"end":103},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":104,"end":105}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot expect boolean as the return type of function because boolean [1] is incompatible with implicitly-returned undefined. [incompatible-return]","context":"function method(): boolean {","source":"-","start":{"line":3,"column":20,"offset":44},"end":{"line":3,"column":26,"offset":51}}],"operation":null}]}
Async functions implicitly return a promise, so the return type must always be a Promise
.
1
2
3
4
|
async function method(): Promise<number> {
return 123;
}
|
{"value":"// @flow\nasync function method(): Promise<number> {\n return 123;\n}\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_ASYNC","context":"normal","value":"async","line":2,"start":9,"end":14},{"type":"T_FUNCTION","context":"normal","value":"function","line":2,"start":15,"end":23},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":2,"start":24,"end":30},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":30,"end":31},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":31,"end":32},{"type":"T_COLON","context":"type","value":":","line":2,"start":32,"end":33},{"type":"T_IDENTIFIER","context":"type","value":"Promise","line":2,"start":34,"end":41},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":41,"end":42},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":42,"end":48},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":48,"end":49},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":50,"end":51},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":54,"end":60},{"type":"T_NUMBER","context":"normal","value":"123","line":3,"start":61,"end":64},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":64,"end":65},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":66,"end":67}],"errors":[]}
Function this
Every function in JavaScript can be called with a special context named this
.
You can call a function with any context that you want. Flow allows you to annotate
the type for this context by adding a special parameter at the start of the function’s parameter list:
1
2
3
4
5
6
7
|
function method<T>(this: { x: T }) : T {
return this.x;
}
var num: number = method.call({x : 42});
var str: string = method.call({x : 42});
|
Cannot assign `method.call(...)` to `str` because number [1] is incompatible with string [2]. [incompatible-type]
{"value":"// @flow\nfunction method<T>(this: { x: T }) : T {\n return this.x;\n}\n\nvar num: number = method.call({x : 42});\nvar str: string = method.call({x : 42}); // 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":"method","line":2,"start":18,"end":24},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":24,"end":25},{"type":"T_IDENTIFIER","context":"type","value":"T","line":2,"start":25,"end":26},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":26,"end":27},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":27,"end":28},{"type":"T_THIS","context":"normal","value":"this","line":2,"start":28,"end":32},{"type":"T_COLON","context":"type","value":":","line":2,"start":32,"end":33},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":34,"end":35},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":2,"start":36,"end":37},{"type":"T_COLON","context":"type","value":":","line":2,"start":37,"end":38},{"type":"T_IDENTIFIER","context":"type","value":"T","line":2,"start":39,"end":40},{"type":"T_RCURLY","context":"type","value":"}","line":2,"start":41,"end":42},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":42,"end":43},{"type":"T_COLON","context":"type","value":":","line":2,"start":44,"end":45},{"type":"T_IDENTIFIER","context":"type","value":"T","line":2,"start":46,"end":47},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":48,"end":49},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":52,"end":58},{"type":"T_THIS","context":"normal","value":"this","line":3,"start":59,"end":63},{"type":"T_PERIOD","context":"normal","value":".","line":3,"start":63,"end":64},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":3,"start":64,"end":65},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":65,"end":66},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":67,"end":68},{"type":"T_VAR","context":"normal","value":"var","line":6,"start":70,"end":73},{"type":"T_IDENTIFIER","context":"normal","value":"num","line":6,"start":74,"end":77},{"type":"T_COLON","context":"type","value":":","line":6,"start":77,"end":78},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":6,"start":79,"end":85},{"type":"T_ASSIGN","context":"normal","value":"=","line":6,"start":86,"end":87},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":6,"start":88,"end":94},{"type":"T_PERIOD","context":"normal","value":".","line":6,"start":94,"end":95},{"type":"T_IDENTIFIER","context":"normal","value":"call","line":6,"start":95,"end":99},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":99,"end":100},{"type":"T_LCURLY","context":"normal","value":"{","line":6,"start":100,"end":101},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":6,"start":101,"end":102},{"type":"T_COLON","context":"normal","value":":","line":6,"start":103,"end":104},{"type":"T_NUMBER","context":"normal","value":"42","line":6,"start":105,"end":107},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":107,"end":108},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":108,"end":109},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":109,"end":110},{"type":"T_VAR","context":"normal","value":"var","line":7,"start":111,"end":114},{"type":"T_IDENTIFIER","context":"normal","value":"str","line":7,"start":115,"end":118},{"type":"T_COLON","context":"type","value":":","line":7,"start":118,"end":119},{"type":"T_STRING_TYPE","context":"type","value":"string","line":7,"start":120,"end":126},{"type":"T_ASSIGN","context":"normal","value":"=","line":7,"start":127,"end":128},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":7,"start":129,"end":135},{"type":"T_PERIOD","context":"normal","value":".","line":7,"start":135,"end":136},{"type":"T_IDENTIFIER","context":"normal","value":"call","line":7,"start":136,"end":140},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":140,"end":141},{"type":"T_LCURLY","context":"normal","value":"{","line":7,"start":141,"end":142},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":7,"start":142,"end":143},{"type":"T_COLON","context":"normal","value":":","line":7,"start":144,"end":145},{"type":"T_NUMBER","context":"normal","value":"42","line":7,"start":146,"end":148},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":148,"end":149},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":149,"end":150},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":150,"end":151},{"type":"Line","context":"comment","value":"// error","line":7,"start":152,"end":160}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot assign `method.call(...)` to `str` because number [1] is incompatible with string [2]. [incompatible-type]","context":"var str: string = method.call({x : 42}); // error","source":"-","start":{"line":7,"column":19,"offset":129},"end":{"line":7,"column":39,"offset":150}}],"operation":null}]}
This parameter has no effect at runtime, and is erased along with types when Flow is transformed into JavaScript.
When present, this
parameters must always appear at the very beginning of the function’s parameter list, and must
have an annotation. Additionally, arrow functions may not have a this
parameter annotation, as
these functions bind their this
parameter at the definition site, rather than the call site.
If an explicit this
parameter is not provided, Flow will attempt to infer one based on usage. If this
is not mentioned
in the body of the function, Flow will infer mixed
for its this
parameter.
Predicate Functions
Sometimes you will want to move the condition from an if
statement into a function:
1
2
3
4
5
6
|
function concat(a: ?string, b: ?string): string {
if (a && b) {
return a + b;
}
return '';
}
|
{"value":"function concat(a: ?string, b: ?string): string {\n if (a && b) {\n return a + b;\n }\n return '';\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_PLING","context":"type","value":"?","line":1,"start":19,"end":20},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":20,"end":26},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":26,"end":27},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":1,"start":28,"end":29},{"type":"T_COLON","context":"type","value":":","line":1,"start":29,"end":30},{"type":"T_PLING","context":"type","value":"?","line":1,"start":31,"end":32},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":32,"end":38},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":38,"end":39},{"type":"T_COLON","context":"type","value":":","line":1,"start":39,"end":40},{"type":"T_STRING_TYPE","context":"type","value":"string","line":1,"start":41,"end":47},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":48,"end":49},{"type":"T_IF","context":"normal","value":"if","line":2,"start":52,"end":54},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":55,"end":56},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":2,"start":56,"end":57},{"type":"T_AND","context":"normal","value":"&&","line":2,"start":58,"end":60},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":61,"end":62},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":62,"end":63},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":64,"end":65},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":70,"end":76},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":3,"start":77,"end":78},{"type":"T_PLUS","context":"normal","value":"+","line":3,"start":79,"end":80},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":3,"start":81,"end":82},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":82,"end":83},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":86,"end":87},{"type":"T_RETURN","context":"normal","value":"return","line":5,"start":90,"end":96},{"type":"T_STRING","context":"normal","value":"''","line":5,"start":97,"end":99},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":99,"end":100},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":101,"end":102}],"errors":[]}
However, Flow will flag an error in the code below:
1
2
3
4
5
6
7
8
9
10
11
|
function truthy(a, b): boolean {
return a && b;
}
function concat(a: ?string, b: ?string): string {
if (truthy(a, b)) {
return a + b;
}
return '';
}
|
{"value":"function truthy(a, b): boolean {\n return a && b;\n}\n\nfunction concat(a: ?string, b: ?string): string {\n if (truthy(a, b)) {\n // $ExpectError\n return a + b;\n }\n return '';\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"truthy","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_COLON","context":"type","value":":","line":1,"start":21,"end":22},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":1,"start":23,"end":30},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":31,"end":32},{"type":"T_RETURN","context":"normal","value":"return","line":2,"start":35,"end":41},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":2,"start":42,"end":43},{"type":"T_AND","context":"normal","value":"&&","line":2,"start":44,"end":46},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":47,"end":48},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":48,"end":49},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":50,"end":51},{"type":"T_FUNCTION","context":"normal","value":"function","line":5,"start":53,"end":61},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":5,"start":62,"end":68},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":68,"end":69},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":5,"start":69,"end":70},{"type":"T_COLON","context":"type","value":":","line":5,"start":70,"end":71},{"type":"T_PLING","context":"type","value":"?","line":5,"start":72,"end":73},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":73,"end":79},{"type":"T_COMMA","context":"normal","value":",","line":5,"start":79,"end":80},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":5,"start":81,"end":82},{"type":"T_COLON","context":"type","value":":","line":5,"start":82,"end":83},{"type":"T_PLING","context":"type","value":"?","line":5,"start":84,"end":85},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":85,"end":91},{"type":"T_RPAREN","context":"normal","value":")","line":5,"start":91,"end":92},{"type":"T_COLON","context":"type","value":":","line":5,"start":92,"end":93},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":94,"end":100},{"type":"T_LCURLY","context":"normal","value":"{","line":5,"start":101,"end":102},{"type":"T_IF","context":"normal","value":"if","line":6,"start":105,"end":107},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":108,"end":109},{"type":"T_IDENTIFIER","context":"normal","value":"truthy","line":6,"start":109,"end":115},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":115,"end":116},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":6,"start":116,"end":117},{"type":"T_COMMA","context":"normal","value":",","line":6,"start":117,"end":118},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":6,"start":119,"end":120},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":120,"end":121},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":121,"end":122},{"type":"T_LCURLY","context":"normal","value":"{","line":6,"start":123,"end":124},{"type":"Line","context":"comment","value":"// $ExpectError","line":7,"start":129,"end":144},{"type":"T_RETURN","context":"normal","value":"return","line":8,"start":149,"end":155},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":8,"start":156,"end":157},{"type":"T_PLUS","context":"normal","value":"+","line":8,"start":158,"end":159},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":8,"start":160,"end":161},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":161,"end":162},{"type":"T_RCURLY","context":"normal","value":"}","line":9,"start":165,"end":166},{"type":"T_RETURN","context":"normal","value":"return","line":10,"start":169,"end":175},{"type":"T_STRING","context":"normal","value":"''","line":10,"start":176,"end":178},{"type":"T_SEMICOLON","context":"normal","value":";","line":10,"start":178,"end":179},{"type":"T_RCURLY","context":"normal","value":"}","line":11,"start":180,"end":181}],"errors":[]}
You can fix this by making truthy
a predicate function, by using
the %checks
annotation like so:
1
2
3
4
5
6
7
8
9
10
|
function truthy(a, b): boolean %checks {
return !!a && !!b;
}
function concat(a: ?string, b: ?string): string {
if (truthy(a, b)) {
return a + b;
}
return '';
}
|
{"value":"function truthy(a, b): boolean %checks {\n return !!a && !!b;\n}\n\nfunction concat(a: ?string, b: ?string): string {\n if (truthy(a, b)) {\n return a + b;\n }\n return '';\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"truthy","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_COLON","context":"type","value":":","line":1,"start":21,"end":22},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":1,"start":23,"end":30},{"type":"T_CHECKS","context":"type","value":"%checks","line":1,"start":31,"end":38},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":39,"end":40},{"type":"T_RETURN","context":"normal","value":"return","line":2,"start":43,"end":49},{"type":"T_NOT","context":"normal","value":"!","line":2,"start":50,"end":51},{"type":"T_NOT","context":"normal","value":"!","line":2,"start":51,"end":52},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":2,"start":52,"end":53},{"type":"T_AND","context":"normal","value":"&&","line":2,"start":54,"end":56},{"type":"T_NOT","context":"normal","value":"!","line":2,"start":57,"end":58},{"type":"T_NOT","context":"normal","value":"!","line":2,"start":58,"end":59},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":2,"start":59,"end":60},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":60,"end":61},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":62,"end":63},{"type":"T_FUNCTION","context":"normal","value":"function","line":5,"start":65,"end":73},{"type":"T_IDENTIFIER","context":"normal","value":"concat","line":5,"start":74,"end":80},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":80,"end":81},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":5,"start":81,"end":82},{"type":"T_COLON","context":"type","value":":","line":5,"start":82,"end":83},{"type":"T_PLING","context":"type","value":"?","line":5,"start":84,"end":85},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":85,"end":91},{"type":"T_COMMA","context":"normal","value":",","line":5,"start":91,"end":92},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":5,"start":93,"end":94},{"type":"T_COLON","context":"type","value":":","line":5,"start":94,"end":95},{"type":"T_PLING","context":"type","value":"?","line":5,"start":96,"end":97},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":97,"end":103},{"type":"T_RPAREN","context":"normal","value":")","line":5,"start":103,"end":104},{"type":"T_COLON","context":"type","value":":","line":5,"start":104,"end":105},{"type":"T_STRING_TYPE","context":"type","value":"string","line":5,"start":106,"end":112},{"type":"T_LCURLY","context":"normal","value":"{","line":5,"start":113,"end":114},{"type":"T_IF","context":"normal","value":"if","line":6,"start":117,"end":119},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":120,"end":121},{"type":"T_IDENTIFIER","context":"normal","value":"truthy","line":6,"start":121,"end":127},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":127,"end":128},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":6,"start":128,"end":129},{"type":"T_COMMA","context":"normal","value":",","line":6,"start":129,"end":130},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":6,"start":131,"end":132},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":132,"end":133},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":133,"end":134},{"type":"T_LCURLY","context":"normal","value":"{","line":6,"start":135,"end":136},{"type":"T_RETURN","context":"normal","value":"return","line":7,"start":141,"end":147},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":7,"start":148,"end":149},{"type":"T_PLUS","context":"normal","value":"+","line":7,"start":150,"end":151},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":7,"start":152,"end":153},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":153,"end":154},{"type":"T_RCURLY","context":"normal","value":"}","line":8,"start":157,"end":158},{"type":"T_RETURN","context":"normal","value":"return","line":9,"start":161,"end":167},{"type":"T_STRING","context":"normal","value":"''","line":9,"start":168,"end":170},{"type":"T_SEMICOLON","context":"normal","value":";","line":9,"start":170,"end":171},{"type":"T_RCURLY","context":"normal","value":"}","line":10,"start":172,"end":173}],"errors":[]}
Limitations of predicate functions
The body of these predicate functions need to be expressions (i.e. local variable declarations are not supported).
But it’s possible to call other predicate functions inside a predicate function.
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
function isString(y): %checks {
return typeof y === "string";
}
function isNumber(y): %checks {
return typeof y === "number";
}
function isNumberOrString(y): %checks {
return isString(y) || isNumber(y);
}
function foo(x): string | number {
if (isNumberOrString(x)) {
return x + x;
} else {
return x.length;
}
}
foo('a');
foo(5);
foo([]);
|
{"value":"function isString(y): %checks {\n return typeof y === \"string\";\n}\n\nfunction isNumber(y): %checks {\n return typeof y === \"number\";\n}\n\nfunction isNumberOrString(y): %checks {\n return isString(y) || isNumber(y);\n}\n\nfunction foo(x): string | number {\n if (isNumberOrString(x)) {\n return x + x;\n } else {\n return x.length; // no error, because Flow infers that x can only be an array\n }\n}\n\nfoo('a');\nfoo(5);\nfoo([]);\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"isString","line":1,"start":9,"end":17},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":17,"end":18},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":1,"start":18,"end":19},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":19,"end":20},{"type":"T_COLON","context":"type","value":":","line":1,"start":20,"end":21},{"type":"T_CHECKS","context":"type","value":"%checks","line":1,"start":22,"end":29},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":30,"end":31},{"type":"T_RETURN","context":"normal","value":"return","line":2,"start":34,"end":40},{"type":"T_TYPEOF","context":"normal","value":"typeof","line":2,"start":41,"end":47},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":2,"start":48,"end":49},{"type":"T_STRICT_EQUAL","context":"normal","value":"===","line":2,"start":50,"end":53},{"type":"T_STRING","context":"normal","value":"\"string\"","line":2,"start":54,"end":62},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":62,"end":63},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":64,"end":65},{"type":"T_FUNCTION","context":"normal","value":"function","line":5,"start":67,"end":75},{"type":"T_IDENTIFIER","context":"normal","value":"isNumber","line":5,"start":76,"end":84},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":84,"end":85},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":5,"start":85,"end":86},{"type":"T_RPAREN","context":"normal","value":")","line":5,"start":86,"end":87},{"type":"T_COLON","context":"type","value":":","line":5,"start":87,"end":88},{"type":"T_CHECKS","context":"type","value":"%checks","line":5,"start":89,"end":96},{"type":"T_LCURLY","context":"normal","value":"{","line":5,"start":97,"end":98},{"type":"T_RETURN","context":"normal","value":"return","line":6,"start":101,"end":107},{"type":"T_TYPEOF","context":"normal","value":"typeof","line":6,"start":108,"end":114},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":6,"start":115,"end":116},{"type":"T_STRICT_EQUAL","context":"normal","value":"===","line":6,"start":117,"end":120},{"type":"T_STRING","context":"normal","value":"\"number\"","line":6,"start":121,"end":129},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":129,"end":130},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":131,"end":132},{"type":"T_FUNCTION","context":"normal","value":"function","line":9,"start":134,"end":142},{"type":"T_IDENTIFIER","context":"normal","value":"isNumberOrString","line":9,"start":143,"end":159},{"type":"T_LPAREN","context":"normal","value":"(","line":9,"start":159,"end":160},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":9,"start":160,"end":161},{"type":"T_RPAREN","context":"normal","value":")","line":9,"start":161,"end":162},{"type":"T_COLON","context":"type","value":":","line":9,"start":162,"end":163},{"type":"T_CHECKS","context":"type","value":"%checks","line":9,"start":164,"end":171},{"type":"T_LCURLY","context":"normal","value":"{","line":9,"start":172,"end":173},{"type":"T_RETURN","context":"normal","value":"return","line":10,"start":176,"end":182},{"type":"T_IDENTIFIER","context":"normal","value":"isString","line":10,"start":183,"end":191},{"type":"T_LPAREN","context":"normal","value":"(","line":10,"start":191,"end":192},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":10,"start":192,"end":193},{"type":"T_RPAREN","context":"normal","value":")","line":10,"start":193,"end":194},{"type":"T_OR","context":"normal","value":"||","line":10,"start":195,"end":197},{"type":"T_IDENTIFIER","context":"normal","value":"isNumber","line":10,"start":198,"end":206},{"type":"T_LPAREN","context":"normal","value":"(","line":10,"start":206,"end":207},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":10,"start":207,"end":208},{"type":"T_RPAREN","context":"normal","value":")","line":10,"start":208,"end":209},{"type":"T_SEMICOLON","context":"normal","value":";","line":10,"start":209,"end":210},{"type":"T_RCURLY","context":"normal","value":"}","line":11,"start":211,"end":212},{"type":"T_FUNCTION","context":"normal","value":"function","line":13,"start":214,"end":222},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":13,"start":223,"end":226},{"type":"T_LPAREN","context":"normal","value":"(","line":13,"start":226,"end":227},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":13,"start":227,"end":228},{"type":"T_RPAREN","context":"normal","value":")","line":13,"start":228,"end":229},{"type":"T_COLON","context":"type","value":":","line":13,"start":229,"end":230},{"type":"T_STRING_TYPE","context":"type","value":"string","line":13,"start":231,"end":237},{"type":"T_BIT_OR","context":"type","value":"|","line":13,"start":238,"end":239},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":13,"start":240,"end":246},{"type":"T_LCURLY","context":"normal","value":"{","line":13,"start":247,"end":248},{"type":"T_IF","context":"normal","value":"if","line":14,"start":251,"end":253},{"type":"T_LPAREN","context":"normal","value":"(","line":14,"start":254,"end":255},{"type":"T_IDENTIFIER","context":"normal","value":"isNumberOrString","line":14,"start":255,"end":271},{"type":"T_LPAREN","context":"normal","value":"(","line":14,"start":271,"end":272},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":14,"start":272,"end":273},{"type":"T_RPAREN","context":"normal","value":")","line":14,"start":273,"end":274},{"type":"T_RPAREN","context":"normal","value":")","line":14,"start":274,"end":275},{"type":"T_LCURLY","context":"normal","value":"{","line":14,"start":276,"end":277},{"type":"T_RETURN","context":"normal","value":"return","line":15,"start":282,"end":288},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":15,"start":289,"end":290},{"type":"T_PLUS","context":"normal","value":"+","line":15,"start":291,"end":292},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":15,"start":293,"end":294},{"type":"T_SEMICOLON","context":"normal","value":";","line":15,"start":294,"end":295},{"type":"T_RCURLY","context":"normal","value":"}","line":16,"start":298,"end":299},{"type":"T_ELSE","context":"normal","value":"else","line":16,"start":300,"end":304},{"type":"T_LCURLY","context":"normal","value":"{","line":16,"start":305,"end":306},{"type":"T_RETURN","context":"normal","value":"return","line":17,"start":311,"end":317},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":17,"start":318,"end":319},{"type":"T_PERIOD","context":"normal","value":".","line":17,"start":319,"end":320},{"type":"T_IDENTIFIER","context":"normal","value":"length","line":17,"start":320,"end":326},{"type":"T_SEMICOLON","context":"normal","value":";","line":17,"start":326,"end":327},{"type":"Line","context":"comment","value":"// no error, because Flow infers that x can only be an array","line":17,"start":328,"end":388},{"type":"T_RCURLY","context":"normal","value":"}","line":18,"start":391,"end":392},{"type":"T_RCURLY","context":"normal","value":"}","line":19,"start":393,"end":394},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":21,"start":396,"end":399},{"type":"T_LPAREN","context":"normal","value":"(","line":21,"start":399,"end":400},{"type":"T_STRING","context":"normal","value":"'a'","line":21,"start":400,"end":403},{"type":"T_RPAREN","context":"normal","value":")","line":21,"start":403,"end":404},{"type":"T_SEMICOLON","context":"normal","value":";","line":21,"start":404,"end":405},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":22,"start":406,"end":409},{"type":"T_LPAREN","context":"normal","value":"(","line":22,"start":409,"end":410},{"type":"T_NUMBER","context":"normal","value":"5","line":22,"start":410,"end":411},{"type":"T_RPAREN","context":"normal","value":")","line":22,"start":411,"end":412},{"type":"T_SEMICOLON","context":"normal","value":";","line":22,"start":412,"end":413},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":23,"start":414,"end":417},{"type":"T_LPAREN","context":"normal","value":"(","line":23,"start":417,"end":418},{"type":"T_LBRACKET","context":"normal","value":"[","line":23,"start":418,"end":419},{"type":"T_RBRACKET","context":"normal","value":"]","line":23,"start":419,"end":420},{"type":"T_RPAREN","context":"normal","value":")","line":23,"start":420,"end":421},{"type":"T_SEMICOLON","context":"normal","value":";","line":23,"start":421,"end":422}],"errors":[]}
Another limitation is on the range of predicates that can be encoded. The refinements
that are supported in a predicate function must refer directly to the value that
is passed in as an argument to the respective call.
For example, consider the inlined refinement
1
2
3
4
5
|
declare var obj: { n?: number };
if (obj.n) {
const n: number = obj.n;
}
|
{"value":"declare var obj: { n?: number };\n\nif (obj.n) {\n const n: number = obj.n;\n}\n","tokens":[{"type":"T_DECLARE","context":"normal","value":"declare","line":1,"start":0,"end":7},{"type":"T_VAR","context":"normal","value":"var","line":1,"start":8,"end":11},{"type":"T_IDENTIFIER","context":"normal","value":"obj","line":1,"start":12,"end":15},{"type":"T_COLON","context":"type","value":":","line":1,"start":15,"end":16},{"type":"T_LCURLY","context":"type","value":"{","line":1,"start":17,"end":18},{"type":"T_IDENTIFIER","context":"normal","value":"n","line":1,"start":19,"end":20},{"type":"T_PLING","context":"type","value":"?","line":1,"start":20,"end":21},{"type":"T_COLON","context":"type","value":":","line":1,"start":21,"end":22},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":23,"end":29},{"type":"T_RCURLY","context":"type","value":"}","line":1,"start":30,"end":31},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":31,"end":32},{"type":"T_IF","context":"normal","value":"if","line":3,"start":34,"end":36},{"type":"T_LPAREN","context":"normal","value":"(","line":3,"start":37,"end":38},{"type":"T_IDENTIFIER","context":"normal","value":"obj","line":3,"start":38,"end":41},{"type":"T_PERIOD","context":"normal","value":".","line":3,"start":41,"end":42},{"type":"T_IDENTIFIER","context":"normal","value":"n","line":3,"start":42,"end":43},{"type":"T_RPAREN","context":"normal","value":")","line":3,"start":43,"end":44},{"type":"T_LCURLY","context":"normal","value":"{","line":3,"start":45,"end":46},{"type":"T_CONST","context":"normal","value":"const","line":4,"start":49,"end":54},{"type":"T_IDENTIFIER","context":"normal","value":"n","line":4,"start":55,"end":56},{"type":"T_COLON","context":"type","value":":","line":4,"start":56,"end":57},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":4,"start":58,"end":64},{"type":"T_ASSIGN","context":"normal","value":"=","line":4,"start":65,"end":66},{"type":"T_IDENTIFIER","context":"normal","value":"obj","line":4,"start":67,"end":70},{"type":"T_PERIOD","context":"normal","value":".","line":4,"start":70,"end":71},{"type":"T_IDENTIFIER","context":"normal","value":"n","line":4,"start":71,"end":72},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":72,"end":73},{"type":"T_RCURLY","context":"normal","value":"}","line":5,"start":74,"end":75}],"errors":[]}
Here, Flow will let you refine obj.n
from ?number
to number
. Note that the
refinement here is on the property n
of obj
, rather than obj
itself.
If you tried to create a predicate function
1
2
3
|
function bar(a): %checks {
return a.n;
}
|
{"value":"function bar(a): %checks {\n return a.n;\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":1,"start":9,"end":12},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":12,"end":13},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":1,"start":13,"end":14},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":14,"end":15},{"type":"T_COLON","context":"type","value":":","line":1,"start":15,"end":16},{"type":"T_CHECKS","context":"type","value":"%checks","line":1,"start":17,"end":24},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":25,"end":26},{"type":"T_RETURN","context":"normal","value":"return","line":2,"start":29,"end":35},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":2,"start":36,"end":37},{"type":"T_PERIOD","context":"normal","value":".","line":2,"start":37,"end":38},{"type":"T_IDENTIFIER","context":"normal","value":"n","line":2,"start":38,"end":39},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":39,"end":40},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":41,"end":42}],"errors":[]}
to encode the same condition, then the following refinement would fail
1
2
3
4
|
if (bar(obj)) {
const n: number = obj.n;
}
|
{"value":"if (bar(obj)) {\n // $ExpectError\n const n: number = obj.n;\n}\n","tokens":[{"type":"T_IF","context":"normal","value":"if","line":1,"start":0,"end":2},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":3,"end":4},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":1,"start":4,"end":7},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":7,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"obj","line":1,"start":8,"end":11},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":11,"end":12},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":12,"end":13},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":14,"end":15},{"type":"Line","context":"comment","value":"// $ExpectError","line":2,"start":18,"end":33},{"type":"T_CONST","context":"normal","value":"const","line":3,"start":36,"end":41},{"type":"T_IDENTIFIER","context":"normal","value":"n","line":3,"start":42,"end":43},{"type":"T_COLON","context":"type","value":":","line":3,"start":43,"end":44},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":3,"start":45,"end":51},{"type":"T_ASSIGN","context":"normal","value":"=","line":3,"start":52,"end":53},{"type":"T_IDENTIFIER","context":"normal","value":"obj","line":3,"start":54,"end":57},{"type":"T_PERIOD","context":"normal","value":".","line":3,"start":57,"end":58},{"type":"T_IDENTIFIER","context":"normal","value":"n","line":3,"start":58,"end":59},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":59,"end":60},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":61,"end":62}],"errors":[]}
This is because the only refinements supported through bar
would be on obj
itself.
Callable Objects
Callable objects can be typed, for example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
type CallableObj = {
(number, number): number,
bar: string
};
function add(x, y) {
return x + y;
}
(add: CallableObj);
add.bar = "hello world";
(add: CallableObj);
|
{"value":"type CallableObj = {\n (number, number): number,\n bar: string\n};\n\nfunction add(x, y) {\n return x + y;\n}\n\n// $ExpectError\n(add: CallableObj);\n\nadd.bar = \"hello world\";\n\n(add: CallableObj);\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"CallableObj","line":1,"start":5,"end":16},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":17,"end":18},{"type":"T_LCURLY","context":"type","value":"{","line":1,"start":19,"end":20},{"type":"T_LPAREN","context":"type","value":"(","line":2,"start":23,"end":24},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":24,"end":30},{"type":"T_COMMA","context":"type","value":",","line":2,"start":30,"end":31},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":32,"end":38},{"type":"T_RPAREN","context":"type","value":")","line":2,"start":38,"end":39},{"type":"T_COLON","context":"type","value":":","line":2,"start":39,"end":40},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":41,"end":47},{"type":"T_COMMA","context":"type","value":",","line":2,"start":47,"end":48},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":3,"start":51,"end":54},{"type":"T_COLON","context":"type","value":":","line":3,"start":54,"end":55},{"type":"T_STRING_TYPE","context":"type","value":"string","line":3,"start":56,"end":62},{"type":"T_RCURLY","context":"type","value":"}","line":4,"start":63,"end":64},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":64,"end":65},{"type":"T_FUNCTION","context":"normal","value":"function","line":6,"start":67,"end":75},{"type":"T_IDENTIFIER","context":"normal","value":"add","line":6,"start":76,"end":79},{"type":"T_LPAREN","context":"normal","value":"(","line":6,"start":79,"end":80},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":6,"start":80,"end":81},{"type":"T_COMMA","context":"normal","value":",","line":6,"start":81,"end":82},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":6,"start":83,"end":84},{"type":"T_RPAREN","context":"normal","value":")","line":6,"start":84,"end":85},{"type":"T_LCURLY","context":"normal","value":"{","line":6,"start":86,"end":87},{"type":"T_RETURN","context":"normal","value":"return","line":7,"start":90,"end":96},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":7,"start":97,"end":98},{"type":"T_PLUS","context":"normal","value":"+","line":7,"start":99,"end":100},{"type":"T_IDENTIFIER","context":"normal","value":"y","line":7,"start":101,"end":102},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":102,"end":103},{"type":"T_RCURLY","context":"normal","value":"}","line":8,"start":104,"end":105},{"type":"Line","context":"comment","value":"// $ExpectError","line":10,"start":107,"end":122},{"type":"T_LPAREN","context":"normal","value":"(","line":11,"start":123,"end":124},{"type":"T_IDENTIFIER","context":"normal","value":"add","line":11,"start":124,"end":127},{"type":"T_COLON","context":"type","value":":","line":11,"start":127,"end":128},{"type":"T_IDENTIFIER","context":"type","value":"CallableObj","line":11,"start":129,"end":140},{"type":"T_RPAREN","context":"normal","value":")","line":11,"start":140,"end":141},{"type":"T_SEMICOLON","context":"normal","value":";","line":11,"start":141,"end":142},{"type":"T_IDENTIFIER","context":"normal","value":"add","line":13,"start":144,"end":147},{"type":"T_PERIOD","context":"normal","value":".","line":13,"start":147,"end":148},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":13,"start":148,"end":151},{"type":"T_ASSIGN","context":"normal","value":"=","line":13,"start":152,"end":153},{"type":"T_STRING","context":"normal","value":"\"hello world\"","line":13,"start":154,"end":167},{"type":"T_SEMICOLON","context":"normal","value":";","line":13,"start":167,"end":168},{"type":"T_LPAREN","context":"normal","value":"(","line":15,"start":170,"end":171},{"type":"T_IDENTIFIER","context":"normal","value":"add","line":15,"start":171,"end":174},{"type":"T_COLON","context":"type","value":":","line":15,"start":174,"end":175},{"type":"T_IDENTIFIER","context":"type","value":"CallableObj","line":15,"start":176,"end":187},{"type":"T_RPAREN","context":"normal","value":")","line":15,"start":187,"end":188},{"type":"T_SEMICOLON","context":"normal","value":";","line":15,"start":188,"end":189}],"errors":[]}
Function
Type
NOTE: For new code prefer any
or (...args: Array<any>) => any
. Function
has become an alias to any
and will be
deprecated and removed in a future version of Flow.
Sometimes it is useful to write types that accept arbitrary functions, for
those you should write () => mixed
like this:
1
2
3
|
function method(func: () => mixed) {
}
|
{"value":"function method(func: () => mixed) {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"func","line":1,"start":16,"end":20},{"type":"T_COLON","context":"type","value":":","line":1,"start":20,"end":21},{"type":"T_LPAREN","context":"type","value":"(","line":1,"start":22,"end":23},{"type":"T_RPAREN","context":"type","value":")","line":1,"start":23,"end":24},{"type":"T_ARROW","context":"type","value":"=>","line":1,"start":25,"end":27},{"type":"T_MIXED_TYPE","context":"type","value":"mixed","line":1,"start":28,"end":33},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":33,"end":34},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":35,"end":36},{"type":"Line","context":"comment","value":"// ...","line":2,"start":39,"end":45},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":46,"end":47}],"errors":[]}
However, if you need to opt-out of the type checker, and don’t want to go all
the way to any
, you can instead use (...args: Array<any>) => any
. (Note that any
is unsafe and
should be avoided). For historical reasons, the Function
keyword is still available.
For example, the following code will not report any errors:
1
2
3
4
5
6
7
8
9
|
function method(func: (...args: Array<any>) => any) {
func(1, 2);
func("1", "2");
func({}, []);
}
method(function(a: number, b: number) {
});
|
{"value":"function method(func: (...args: Array<any>) => any) {\n func(1, 2); // Works.\n func(\"1\", \"2\"); // Works.\n func({}, []); // Works.\n}\n\nmethod(function(a: number, b: number) {\n // ...\n});\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"func","line":1,"start":16,"end":20},{"type":"T_COLON","context":"type","value":":","line":1,"start":20,"end":21},{"type":"T_LPAREN","context":"type","value":"(","line":1,"start":22,"end":23},{"type":"T_ELLIPSIS","context":"type","value":"...","line":1,"start":23,"end":26},{"type":"T_IDENTIFIER","context":"normal","value":"args","line":1,"start":26,"end":30},{"type":"T_COLON","context":"type","value":":","line":1,"start":30,"end":31},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":1,"start":32,"end":37},{"type":"T_LESS_THAN","context":"type","value":"<","line":1,"start":37,"end":38},{"type":"T_ANY_TYPE","context":"type","value":"any","line":1,"start":38,"end":41},{"type":"T_GREATER_THAN","context":"type","value":">","line":1,"start":41,"end":42},{"type":"T_RPAREN","context":"type","value":")","line":1,"start":42,"end":43},{"type":"T_ARROW","context":"type","value":"=>","line":1,"start":44,"end":46},{"type":"T_ANY_TYPE","context":"type","value":"any","line":1,"start":47,"end":50},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":50,"end":51},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":52,"end":53},{"type":"T_IDENTIFIER","context":"normal","value":"func","line":2,"start":56,"end":60},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":60,"end":61},{"type":"T_NUMBER","context":"normal","value":"1","line":2,"start":61,"end":62},{"type":"T_COMMA","context":"normal","value":",","line":2,"start":62,"end":63},{"type":"T_NUMBER","context":"normal","value":"2","line":2,"start":64,"end":65},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":65,"end":66},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":66,"end":67},{"type":"Line","context":"comment","value":"// Works.","line":2,"start":72,"end":81},{"type":"T_IDENTIFIER","context":"normal","value":"func","line":3,"start":84,"end":88},{"type":"T_LPAREN","context":"normal","value":"(","line":3,"start":88,"end":89},{"type":"T_STRING","context":"normal","value":"\"1\"","line":3,"start":89,"end":92},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":92,"end":93},{"type":"T_STRING","context":"normal","value":"\"2\"","line":3,"start":94,"end":97},{"type":"T_RPAREN","context":"normal","value":")","line":3,"start":97,"end":98},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":98,"end":99},{"type":"Line","context":"comment","value":"// Works.","line":3,"start":100,"end":109},{"type":"T_IDENTIFIER","context":"normal","value":"func","line":4,"start":112,"end":116},{"type":"T_LPAREN","context":"normal","value":"(","line":4,"start":116,"end":117},{"type":"T_LCURLY","context":"normal","value":"{","line":4,"start":117,"end":118},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":118,"end":119},{"type":"T_COMMA","context":"normal","value":",","line":4,"start":119,"end":120},{"type":"T_LBRACKET","context":"normal","value":"[","line":4,"start":121,"end":122},{"type":"T_RBRACKET","context":"normal","value":"]","line":4,"start":122,"end":123},{"type":"T_RPAREN","context":"normal","value":")","line":4,"start":123,"end":124},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":124,"end":125},{"type":"Line","context":"comment","value":"// Works.","line":4,"start":128,"end":137},{"type":"T_RCURLY","context":"normal","value":"}","line":5,"start":138,"end":139},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":7,"start":141,"end":147},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":147,"end":148},{"type":"T_FUNCTION","context":"normal","value":"function","line":7,"start":148,"end":156},{"type":"T_LPAREN","context":"normal","value":"(","line":7,"start":156,"end":157},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":7,"start":157,"end":158},{"type":"T_COLON","context":"type","value":":","line":7,"start":158,"end":159},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":7,"start":160,"end":166},{"type":"T_COMMA","context":"normal","value":",","line":7,"start":166,"end":167},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":7,"start":168,"end":169},{"type":"T_COLON","context":"type","value":":","line":7,"start":169,"end":170},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":7,"start":171,"end":177},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":177,"end":178},{"type":"T_LCURLY","context":"normal","value":"{","line":7,"start":179,"end":180},{"type":"Line","context":"comment","value":"// ...","line":8,"start":183,"end":189},{"type":"T_RCURLY","context":"normal","value":"}","line":9,"start":190,"end":191},{"type":"T_RPAREN","context":"normal","value":")","line":9,"start":191,"end":192},{"type":"T_SEMICOLON","context":"normal","value":";","line":9,"start":192,"end":193}],"errors":[]}
Neither will this:
1
2
3
4
5
6
7
|
function method(obj: Function) {
obj = 10;
}
method(function(a: number, b: number) {
});
|
{"value":"function method(obj: Function) {\n obj = 10;\n}\n\nmethod(function(a: number, b: number) {\n // ...\n});\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":1,"start":9,"end":15},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"normal","value":"obj","line":1,"start":16,"end":19},{"type":"T_COLON","context":"type","value":":","line":1,"start":19,"end":20},{"type":"T_IDENTIFIER","context":"type","value":"Function","line":1,"start":21,"end":29},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":29,"end":30},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":31,"end":32},{"type":"T_IDENTIFIER","context":"normal","value":"obj","line":2,"start":35,"end":38},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":39,"end":40},{"type":"T_NUMBER","context":"normal","value":"10","line":2,"start":41,"end":43},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":43,"end":44},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":45,"end":46},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":5,"start":48,"end":54},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":54,"end":55},{"type":"T_FUNCTION","context":"normal","value":"function","line":5,"start":55,"end":63},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":63,"end":64},{"type":"T_IDENTIFIER","context":"normal","value":"a","line":5,"start":64,"end":65},{"type":"T_COLON","context":"type","value":":","line":5,"start":65,"end":66},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":5,"start":67,"end":73},{"type":"T_COMMA","context":"normal","value":",","line":5,"start":73,"end":74},{"type":"T_IDENTIFIER","context":"normal","value":"b","line":5,"start":75,"end":76},{"type":"T_COLON","context":"type","value":":","line":5,"start":76,"end":77},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":5,"start":78,"end":84},{"type":"T_RPAREN","context":"normal","value":")","line":5,"start":84,"end":85},{"type":"T_LCURLY","context":"normal","value":"{","line":5,"start":86,"end":87},{"type":"Line","context":"comment","value":"// ...","line":6,"start":90,"end":96},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":97,"end":98},{"type":"T_RPAREN","context":"normal","value":")","line":7,"start":98,"end":99},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":99,"end":100}],"errors":[]}
You should follow all the same rules as any
when using
Function
.