Closed
Description
class Square {
length : number;
constructor(length : number) {
this.length = length;
}
}
class Rectangle {
length : number;
width : number;
constructor(length : number, width : number) {
this.length = length;
this.width = width;
}
}
class Triangle {
base : number
height : number;
constructor(base : number, height : number) {
this.base = base;
this.height = height;
}
}
The following works as expected:
namespace function_overloading_with_any {
function calculateArea(shape : Square) : number; // overloaded signature
function calculateArea(shape : Rectangle) : number; // overloaded signature
function calculateArea(shape : Triangle) : number; // overloaded signature
function calculateArea(shape : any) : number // implementation signature
{
if(shape instanceof Square) {
return shape.length * shape.length;
}
else if(shape instanceof Rectangle) {
return shape.length * shape.width;
}
else if(shape instanceof Triangle) {
return (shape.base * shape.height) / 2;
}
}
var square = new Square(5);
var rectangle = new Rectangle(3, 5);
var triangle = new Triangle(3, 5);
calculateArea(square);
calculateArea(rectangle);
calculateArea(triangle);
}
However, when I use an union type instead of any
in the implementation signature:
namespace chapter02.function_overloading.with_union {
function calculateArea(shape : Square) : number;
function calculateArea(shape : Rectangle) : number;
function calculateArea(shape : Triangle) : number;
function calculateArea(shape : (Square | Rectangle | Triangle)) : number {
if(shape instanceof Square) {
return shape.length * shape.length;
}
else if(shape instanceof Rectangle) {
return shape.length * shape.width; // Error!
}
else if(shape instanceof Triangle) {
return (shape.base * shape.height) / 2;
}
}
var square = new Square(5);
var rectangle = new Rectangle(3, 5);
var triangle = new Triangle(3, 5);
calculateArea(square);
calculateArea(rectangle);
calculateArea(triangle);
}
I get a compilation error:
error TS2339: Property 'length' does not exist on type 'Triangle'.
error TS2339: Property 'width' does not exist on type 'Triangle'.
Looks like the type guard is not working as expected. I can use an if
instead of if else
to fix the error:
function calculateArea(shape : Square) : number;
function calculateArea(shape : Rectangle) : number;
function calculateArea(shape : Triangle) : number;
function calculateArea(shape : (Square | Rectangle | Triangle)) : number {
if(shape instanceof Square) {
return shape.length * shape.length;
}
if(shape instanceof Rectangle) {
return shape.length * shape.width; // OK!
}
if(shape instanceof Triangle) {
return (shape.base * shape.height) / 2;
}
}
I'm using TypeScript 1.8.0-dev.20151129
with gulp-typescript:
gulp.task('build', ['lint'], function() {
var tsProject = ts.createProject('tsconfig.json', {
typescript: require('typescript')
});
var compile = ts(tsProject);
return gulp.src("src/**/**.ts")
.pipe(compile)
.js.pipe(gulp.dest("src/"));
});
And the following tsconfig.json
compilation:
{
"compilerOptions": {
"target": "es5",
"module": "umd",
"moduleResolution": "node",
"isolatedModules": false,
"jsx": "react",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"preserveConstEnums": true,
"suppressImplicitAnyIndexErrors": true
}
}
The source code that I used to discover this issue can be found here.
Thanks!