JavaScript classes
in Flow operate both as a value and a type.
You write classes the same way you would without Flow, but then you can use the
name of the class as a type.
1
2
3
4
5
|
class MyClass {
}
let myInstance: MyClass = new MyClass();
|
{"value":"class MyClass {\n // ...\n}\n\nlet myInstance: MyClass = new MyClass();\n","tokens":[{"type":"T_CLASS","context":"normal","value":"class","line":1,"start":0,"end":5},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":1,"start":6,"end":13},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":14,"end":15},{"type":"Line","context":"comment","value":"// ...","line":2,"start":18,"end":24},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":25,"end":26},{"type":"T_LET","context":"normal","value":"let","line":5,"start":28,"end":31},{"type":"T_IDENTIFIER","context":"normal","value":"myInstance","line":5,"start":32,"end":42},{"type":"T_COLON","context":"type","value":":","line":5,"start":42,"end":43},{"type":"T_IDENTIFIER","context":"type","value":"MyClass","line":5,"start":44,"end":51},{"type":"T_ASSIGN","context":"normal","value":"=","line":5,"start":52,"end":53},{"type":"T_NEW","context":"normal","value":"new","line":5,"start":54,"end":57},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":5,"start":58,"end":65},{"type":"T_LPAREN","context":"normal","value":"(","line":5,"start":65,"end":66},{"type":"T_RPAREN","context":"normal","value":")","line":5,"start":66,"end":67},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":67,"end":68}],"errors":[]}
This is because classes in Flow are nominally typed.
Class Syntax
Classes in Flow are identical to normal JavaScript classes, but with added
types.
Class Methods
Just like in functions, class methods can have annotations for both parameters
(input) and returns (output).
1
2
3
|
class MyClass {
method(value: string): number { }
}
|
{"value":"class MyClass {\n method(value: string): number { /* ... */ }\n}\n","tokens":[{"type":"T_CLASS","context":"normal","value":"class","line":1,"start":0,"end":5},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":1,"start":6,"end":13},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":14,"end":15},{"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":"value","line":2,"start":25,"end":30},{"type":"T_COLON","context":"type","value":":","line":2,"start":30,"end":31},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":32,"end":38},{"type":"T_RPAREN","context":"normal","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_LCURLY","context":"normal","value":"{","line":2,"start":48,"end":49},{"type":"Block","context":"comment","value":"/* ... */","line":2,"start":50,"end":59},{"type":"T_RCURLY","context":"normal","value":"}","line":2,"start":60,"end":61},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":62,"end":63}],"errors":[]}
Class Fields (Properties)
Whenever you want to use a class field in Flow you must first give it an
annotation.
1
2
3
4
5
6
7
|
class MyClass {
method() {
this.prop = 42;
}
}
|
Cannot assign `42` to `this.prop` because property `prop` is missing in `MyClass` [1]. [prop-missing]
{"value":"// @flow\nclass MyClass {\n method() {\n // $ExpectError\n this.prop = 42; // Error!\n }\n}\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_CLASS","context":"normal","value":"class","line":2,"start":9,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":2,"start":15,"end":22},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":23,"end":24},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":3,"start":27,"end":33},{"type":"T_LPAREN","context":"normal","value":"(","line":3,"start":33,"end":34},{"type":"T_RPAREN","context":"normal","value":")","line":3,"start":34,"end":35},{"type":"T_LCURLY","context":"normal","value":"{","line":3,"start":36,"end":37},{"type":"Line","context":"comment","value":"// $ExpectError","line":4,"start":42,"end":57},{"type":"T_THIS","context":"normal","value":"this","line":5,"start":62,"end":66},{"type":"T_PERIOD","context":"normal","value":".","line":5,"start":66,"end":67},{"type":"T_IDENTIFIER","context":"normal","value":"prop","line":5,"start":67,"end":71},{"type":"T_ASSIGN","context":"normal","value":"=","line":5,"start":72,"end":73},{"type":"T_NUMBER","context":"normal","value":"42","line":5,"start":74,"end":76},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":76,"end":77},{"type":"Line","context":"comment","value":"// Error!","line":5,"start":78,"end":87},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":90,"end":91},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":92,"end":93}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot assign `42` to `this.prop` because property `prop` is missing in `MyClass` [1]. [prop-missing]","context":" this.prop = 42; // Error!","source":"-","start":{"line":5,"column":10,"offset":67},"end":{"line":5,"column":13,"offset":71}}],"operation":null}]}
Fields are annotated within the body of the class with the field name followed
by a colon :
and the type.
1
2
3
4
5
6
7
|
class MyClass {
prop: number;
method() {
this.prop = 42;
}
}
|
{"value":"// @flow\nclass MyClass {\n prop: number;\n method() {\n this.prop = 42;\n }\n}\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_CLASS","context":"normal","value":"class","line":2,"start":9,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":2,"start":15,"end":22},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":23,"end":24},{"type":"T_IDENTIFIER","context":"normal","value":"prop","line":3,"start":27,"end":31},{"type":"T_COLON","context":"type","value":":","line":3,"start":31,"end":32},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":3,"start":33,"end":39},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":39,"end":40},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":4,"start":43,"end":49},{"type":"T_LPAREN","context":"normal","value":"(","line":4,"start":49,"end":50},{"type":"T_RPAREN","context":"normal","value":")","line":4,"start":50,"end":51},{"type":"T_LCURLY","context":"normal","value":"{","line":4,"start":52,"end":53},{"type":"T_THIS","context":"normal","value":"this","line":5,"start":58,"end":62},{"type":"T_PERIOD","context":"normal","value":".","line":5,"start":62,"end":63},{"type":"T_IDENTIFIER","context":"normal","value":"prop","line":5,"start":63,"end":67},{"type":"T_ASSIGN","context":"normal","value":"=","line":5,"start":68,"end":69},{"type":"T_NUMBER","context":"normal","value":"42","line":5,"start":70,"end":72},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":72,"end":73},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":76,"end":77},{"type":"T_RCURLY","context":"normal","value":"}","line":7,"start":78,"end":79}],"errors":[]}
Fields added outside of the class definition need to be annotated within the body
of the class.
1
2
3
4
5
6
7
8
9
10
11
12
|
function func_we_use_everywhere (x: number): number {
return x + 1;
}
class MyClass {
static constant: number;
static helper: (number) => number;
method: number => number;
}
MyClass.helper = func_we_use_everywhere
MyClass.constant = 42
MyClass.prototype.method = func_we_use_everywhere
|
{"value":"// @flow\nfunction func_we_use_everywhere (x: number): number {\n return x + 1;\n}\nclass MyClass {\n static constant: number;\n static helper: (number) => number;\n method: number => number;\n}\nMyClass.helper = func_we_use_everywhere\nMyClass.constant = 42\nMyClass.prototype.method = func_we_use_everywhere\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":"func_we_use_everywhere","line":2,"start":18,"end":40},{"type":"T_LPAREN","context":"normal","value":"(","line":2,"start":41,"end":42},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":2,"start":42,"end":43},{"type":"T_COLON","context":"type","value":":","line":2,"start":43,"end":44},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":45,"end":51},{"type":"T_RPAREN","context":"normal","value":")","line":2,"start":51,"end":52},{"type":"T_COLON","context":"type","value":":","line":2,"start":52,"end":53},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":54,"end":60},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":61,"end":62},{"type":"T_RETURN","context":"normal","value":"return","line":3,"start":65,"end":71},{"type":"T_IDENTIFIER","context":"normal","value":"x","line":3,"start":72,"end":73},{"type":"T_PLUS","context":"normal","value":"+","line":3,"start":74,"end":75},{"type":"T_NUMBER","context":"normal","value":"1","line":3,"start":76,"end":77},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":77,"end":78},{"type":"T_RCURLY","context":"normal","value":"}","line":4,"start":79,"end":80},{"type":"T_CLASS","context":"normal","value":"class","line":5,"start":81,"end":86},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":5,"start":87,"end":94},{"type":"T_LCURLY","context":"normal","value":"{","line":5,"start":95,"end":96},{"type":"T_STATIC","context":"normal","value":"static","line":6,"start":99,"end":105},{"type":"T_IDENTIFIER","context":"normal","value":"constant","line":6,"start":106,"end":114},{"type":"T_COLON","context":"type","value":":","line":6,"start":114,"end":115},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":6,"start":116,"end":122},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":122,"end":123},{"type":"T_STATIC","context":"normal","value":"static","line":7,"start":126,"end":132},{"type":"T_IDENTIFIER","context":"normal","value":"helper","line":7,"start":133,"end":139},{"type":"T_COLON","context":"type","value":":","line":7,"start":139,"end":140},{"type":"T_LPAREN","context":"type","value":"(","line":7,"start":141,"end":142},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":7,"start":142,"end":148},{"type":"T_RPAREN","context":"type","value":")","line":7,"start":148,"end":149},{"type":"T_ARROW","context":"type","value":"=>","line":7,"start":150,"end":152},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":7,"start":153,"end":159},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":159,"end":160},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":8,"start":163,"end":169},{"type":"T_COLON","context":"type","value":":","line":8,"start":169,"end":170},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":8,"start":171,"end":177},{"type":"T_ARROW","context":"type","value":"=>","line":8,"start":178,"end":180},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":8,"start":181,"end":187},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":187,"end":188},{"type":"T_RCURLY","context":"normal","value":"}","line":9,"start":189,"end":190},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":10,"start":191,"end":198},{"type":"T_PERIOD","context":"normal","value":".","line":10,"start":198,"end":199},{"type":"T_IDENTIFIER","context":"normal","value":"helper","line":10,"start":199,"end":205},{"type":"T_ASSIGN","context":"normal","value":"=","line":10,"start":206,"end":207},{"type":"T_IDENTIFIER","context":"normal","value":"func_we_use_everywhere","line":10,"start":208,"end":230},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":11,"start":231,"end":238},{"type":"T_PERIOD","context":"normal","value":".","line":11,"start":238,"end":239},{"type":"T_IDENTIFIER","context":"normal","value":"constant","line":11,"start":239,"end":247},{"type":"T_ASSIGN","context":"normal","value":"=","line":11,"start":248,"end":249},{"type":"T_NUMBER","context":"normal","value":"42","line":11,"start":250,"end":252},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":12,"start":253,"end":260},{"type":"T_PERIOD","context":"normal","value":".","line":12,"start":260,"end":261},{"type":"T_IDENTIFIER","context":"normal","value":"prototype","line":12,"start":261,"end":270},{"type":"T_PERIOD","context":"normal","value":".","line":12,"start":270,"end":271},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":12,"start":271,"end":277},{"type":"T_ASSIGN","context":"normal","value":"=","line":12,"start":278,"end":279},{"type":"T_IDENTIFIER","context":"normal","value":"func_we_use_everywhere","line":12,"start":280,"end":302}],"errors":[]}
Flow also supports using the class properties syntax.
1
2
3
|
class MyClass {
prop = 42;
}
|
{"value":"class MyClass {\n prop = 42;\n}\n","tokens":[{"type":"T_CLASS","context":"normal","value":"class","line":1,"start":0,"end":5},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":1,"start":6,"end":13},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":14,"end":15},{"type":"T_IDENTIFIER","context":"normal","value":"prop","line":2,"start":18,"end":22},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":23,"end":24},{"type":"T_NUMBER","context":"normal","value":"42","line":2,"start":25,"end":27},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":27,"end":28},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":29,"end":30}],"errors":[]}
When using this syntax, you are not required to give it a type annotation. But
you still can if you need to.
1
2
3
|
class MyClass {
prop: number = 42;
}
|
{"value":"class MyClass {\n prop: number = 42;\n}\n","tokens":[{"type":"T_CLASS","context":"normal","value":"class","line":1,"start":0,"end":5},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":1,"start":6,"end":13},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":14,"end":15},{"type":"T_IDENTIFIER","context":"normal","value":"prop","line":2,"start":18,"end":22},{"type":"T_COLON","context":"type","value":":","line":2,"start":22,"end":23},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":24,"end":30},{"type":"T_ASSIGN","context":"normal","value":"=","line":2,"start":31,"end":32},{"type":"T_NUMBER","context":"normal","value":"42","line":2,"start":33,"end":35},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":35,"end":36},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":37,"end":38}],"errors":[]}
Class Generics
Classes can also have their own generics.
1
2
3
4
5
6
|
class MyClass<A, B, C> {
property: A;
method(val: B): C {
}
}
|
{"value":"class MyClass<A, B, C> {\n property: A;\n method(val: B): C {\n // ...\n }\n}\n","tokens":[{"type":"T_CLASS","context":"normal","value":"class","line":1,"start":0,"end":5},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":1,"start":6,"end":13},{"type":"T_LESS_THAN","context":"type","value":"<","line":1,"start":13,"end":14},{"type":"T_IDENTIFIER","context":"type","value":"A","line":1,"start":14,"end":15},{"type":"T_COMMA","context":"type","value":",","line":1,"start":15,"end":16},{"type":"T_IDENTIFIER","context":"type","value":"B","line":1,"start":17,"end":18},{"type":"T_COMMA","context":"type","value":",","line":1,"start":18,"end":19},{"type":"T_IDENTIFIER","context":"type","value":"C","line":1,"start":20,"end":21},{"type":"T_GREATER_THAN","context":"type","value":">","line":1,"start":21,"end":22},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":23,"end":24},{"type":"T_IDENTIFIER","context":"normal","value":"property","line":2,"start":27,"end":35},{"type":"T_COLON","context":"type","value":":","line":2,"start":35,"end":36},{"type":"T_IDENTIFIER","context":"type","value":"A","line":2,"start":37,"end":38},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":38,"end":39},{"type":"T_IDENTIFIER","context":"normal","value":"method","line":3,"start":42,"end":48},{"type":"T_LPAREN","context":"normal","value":"(","line":3,"start":48,"end":49},{"type":"T_IDENTIFIER","context":"normal","value":"val","line":3,"start":49,"end":52},{"type":"T_COLON","context":"type","value":":","line":3,"start":52,"end":53},{"type":"T_IDENTIFIER","context":"type","value":"B","line":3,"start":54,"end":55},{"type":"T_RPAREN","context":"normal","value":")","line":3,"start":55,"end":56},{"type":"T_COLON","context":"type","value":":","line":3,"start":56,"end":57},{"type":"T_IDENTIFIER","context":"type","value":"C","line":3,"start":58,"end":59},{"type":"T_LCURLY","context":"normal","value":"{","line":3,"start":60,"end":61},{"type":"Line","context":"comment","value":"// ...","line":4,"start":66,"end":72},{"type":"T_RCURLY","context":"normal","value":"}","line":5,"start":75,"end":76},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":77,"end":78}],"errors":[]}
Class generics are parameterized.
When you use a class as a type you need to pass parameters for each of its
generics.
1
2
3
4
5
6
7
8
|
class MyClass<A, B, C> {
constructor(arg1: A, arg2: B, arg3: C) {
}
}
var val: MyClass<number, boolean, string> = new MyClass(1, true, 'three');
|
{"value":"// @flow\nclass MyClass<A, B, C> {\n constructor(arg1: A, arg2: B, arg3: C) {\n // ...\n }\n}\n\nvar val: MyClass<number, boolean, string> = new MyClass(1, true, 'three');\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_CLASS","context":"normal","value":"class","line":2,"start":9,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":2,"start":15,"end":22},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":22,"end":23},{"type":"T_IDENTIFIER","context":"type","value":"A","line":2,"start":23,"end":24},{"type":"T_COMMA","context":"type","value":",","line":2,"start":24,"end":25},{"type":"T_IDENTIFIER","context":"type","value":"B","line":2,"start":26,"end":27},{"type":"T_COMMA","context":"type","value":",","line":2,"start":27,"end":28},{"type":"T_IDENTIFIER","context":"type","value":"C","line":2,"start":29,"end":30},{"type":"T_GREATER_THAN","context":"type","value":">","line":2,"start":30,"end":31},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":32,"end":33},{"type":"T_IDENTIFIER","context":"normal","value":"constructor","line":3,"start":36,"end":47},{"type":"T_LPAREN","context":"normal","value":"(","line":3,"start":47,"end":48},{"type":"T_IDENTIFIER","context":"normal","value":"arg1","line":3,"start":48,"end":52},{"type":"T_COLON","context":"type","value":":","line":3,"start":52,"end":53},{"type":"T_IDENTIFIER","context":"type","value":"A","line":3,"start":54,"end":55},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":55,"end":56},{"type":"T_IDENTIFIER","context":"normal","value":"arg2","line":3,"start":57,"end":61},{"type":"T_COLON","context":"type","value":":","line":3,"start":61,"end":62},{"type":"T_IDENTIFIER","context":"type","value":"B","line":3,"start":63,"end":64},{"type":"T_COMMA","context":"normal","value":",","line":3,"start":64,"end":65},{"type":"T_IDENTIFIER","context":"normal","value":"arg3","line":3,"start":66,"end":70},{"type":"T_COLON","context":"type","value":":","line":3,"start":70,"end":71},{"type":"T_IDENTIFIER","context":"type","value":"C","line":3,"start":72,"end":73},{"type":"T_RPAREN","context":"normal","value":")","line":3,"start":73,"end":74},{"type":"T_LCURLY","context":"normal","value":"{","line":3,"start":75,"end":76},{"type":"Line","context":"comment","value":"// ...","line":4,"start":81,"end":87},{"type":"T_RCURLY","context":"normal","value":"}","line":5,"start":90,"end":91},{"type":"T_RCURLY","context":"normal","value":"}","line":6,"start":92,"end":93},{"type":"T_VAR","context":"normal","value":"var","line":8,"start":95,"end":98},{"type":"T_IDENTIFIER","context":"normal","value":"val","line":8,"start":99,"end":102},{"type":"T_COLON","context":"type","value":":","line":8,"start":102,"end":103},{"type":"T_IDENTIFIER","context":"type","value":"MyClass","line":8,"start":104,"end":111},{"type":"T_LESS_THAN","context":"type","value":"<","line":8,"start":111,"end":112},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":8,"start":112,"end":118},{"type":"T_COMMA","context":"type","value":",","line":8,"start":118,"end":119},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":8,"start":120,"end":127},{"type":"T_COMMA","context":"type","value":",","line":8,"start":127,"end":128},{"type":"T_STRING_TYPE","context":"type","value":"string","line":8,"start":129,"end":135},{"type":"T_GREATER_THAN","context":"type","value":">","line":8,"start":135,"end":136},{"type":"T_ASSIGN","context":"normal","value":"=","line":8,"start":137,"end":138},{"type":"T_NEW","context":"normal","value":"new","line":8,"start":139,"end":142},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":8,"start":143,"end":150},{"type":"T_LPAREN","context":"normal","value":"(","line":8,"start":150,"end":151},{"type":"T_NUMBER","context":"normal","value":"1","line":8,"start":151,"end":152},{"type":"T_COMMA","context":"normal","value":",","line":8,"start":152,"end":153},{"type":"T_TRUE","context":"normal","value":"true","line":8,"start":154,"end":158},{"type":"T_COMMA","context":"normal","value":",","line":8,"start":158,"end":159},{"type":"T_STRING","context":"normal","value":"'three'","line":8,"start":160,"end":167},{"type":"T_RPAREN","context":"normal","value":")","line":8,"start":167,"end":168},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":168,"end":169}],"errors":[]}
Classes in annotations
When you use the name of your class in an annotation, it means an instance of your class:
1
2
3
4
|
class MyClass {}
(MyClass: MyClass);
(new MyClass(): MyClass);
|
Cannot cast `MyClass` to `MyClass` because class `MyClass` [1] is incompatible with `MyClass` [2]. [incompatible-cast]
{"value":"//@flow\nclass MyClass {}\n(MyClass: MyClass); // Error\n(new MyClass(): MyClass); // Ok\n","tokens":[{"type":"Line","context":"comment","value":"//@flow","line":1,"start":0,"end":7},{"type":"T_CLASS","context":"normal","value":"class","line":2,"start":8,"end":13},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":2,"start":14,"end":21},{"type":"T_LCURLY","context":"normal","value":"{","line":2,"start":22,"end":23},{"type":"T_RCURLY","context":"normal","value":"}","line":2,"start":23,"end":24},{"type":"T_LPAREN","context":"normal","value":"(","line":3,"start":25,"end":26},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":3,"start":26,"end":33},{"type":"T_COLON","context":"type","value":":","line":3,"start":33,"end":34},{"type":"T_IDENTIFIER","context":"type","value":"MyClass","line":3,"start":35,"end":42},{"type":"T_RPAREN","context":"normal","value":")","line":3,"start":42,"end":43},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":43,"end":44},{"type":"Line","context":"comment","value":"// Error","line":3,"start":45,"end":53},{"type":"T_LPAREN","context":"normal","value":"(","line":4,"start":54,"end":55},{"type":"T_NEW","context":"normal","value":"new","line":4,"start":55,"end":58},{"type":"T_IDENTIFIER","context":"normal","value":"MyClass","line":4,"start":59,"end":66},{"type":"T_LPAREN","context":"normal","value":"(","line":4,"start":66,"end":67},{"type":"T_RPAREN","context":"normal","value":")","line":4,"start":67,"end":68},{"type":"T_COLON","context":"type","value":":","line":4,"start":68,"end":69},{"type":"T_IDENTIFIER","context":"type","value":"MyClass","line":4,"start":70,"end":77},{"type":"T_RPAREN","context":"normal","value":")","line":4,"start":77,"end":78},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":78,"end":79},{"type":"Line","context":"comment","value":"// Ok","line":4,"start":80,"end":85}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot cast `MyClass` to `MyClass` because class `MyClass` [1] is incompatible with `MyClass` [2]. [incompatible-cast]","context":"(MyClass: MyClass); // Error","source":"-","start":{"line":3,"column":2,"offset":26},"end":{"line":3,"column":8,"offset":33}}],"operation":null}]}
See here for details on Class<T>
, which allows you
to refer to the type of the class in an annotation.