import ballerina/io;
type Vehicle record {|
string mode;
string color;
string make;
string ...; // rest field
|};
type AeroPlance record {|
*Vehicle;
string noOfEngines;
|};
type Helicopter record {|
*Vehicle;
string noOfRotors;
|};
public function main(string[] args) {
AeroPlance|Helicopter flight = getFlight();
if (flight is AeroPlance) {
printAeroPlance(flight);
} else {
printHelicopter(flight);
}
}
function getFlight() returns AeroPlance|Helicopter {
return {mode:"Air", color:"Red", "make": "Boeing", noOfEngines:"2"};
}
function printAeroPlance(AeroPlance aeroPlance) {
io:println("AeroPlance:", aeroPlance);
}
function printHelicopter(Helicopter helicopter) {
io:println("Helicopter: ", helicopter);
}
In the above code, type narrowing doesn't work as expected when the Vehicle
record is defined with a rest field. I'm getting the following compilation error.
ERROR [b.bal:(26:25,26:31)] incompatible types: expected 'Helicopter', found '(AeroPlance|Helicopter)'
However, this works when the rest field is removed from the Vehicle
record. What is the reason for this behavior?
This is because of how typing and type narrowing is defined at the moment with open records (
Vehicle
is an open record, and therefore theAeroPlane
andHelicopter
records are also open). Although the jBallerina implementation doesn't allow it, since the records are open and mutable. the specification says a value of a type likeis valid for
AeroPlane|Helicopter
.Therefore, the type cannot be narrowed to
Helicopter
in the else block. If the values were closed or immutable, narrowing would work as expected in the sample.