I came across the following code snippet:
const myObject = new Object();
myObject['test'] = 'hello';
calc(myObject['test']);
function calc(x: number) {
console.log(x * 10);
}
This example is quite straightforward.
I expected TypeScript to raise a compile-time error indicating that it cannot determine the concrete type while calc
expects a number.
To my surprise, TypeScript remained silent and the console displayed NaN
.
The issue caught my attention when working with Angular 4 and routing data.
const routes: Routes = [
{
path: '**',
data: [{error: new ApplicationError('http-status-404', '', HttpErrorStatus.NotFound)}],
component: ApplicationErrorComponent,
resolve: {
error: ApplicationErrorResolve
}
}
];
@Injectable()
export class ApplicationErrorResolve implements Resolve<ApplicationError> {
constructor(private applicationErrorHandler: ApplicationErrorHandler) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): ApplicationError {
if (route.data != null && route.data[0]['error'] instanceof ApplicationError) {
this.applicationErrorHandler.addError(route.data[0]);
return route.data[0];
}
return null;
}
}
// signature of applicationErrorHandler.addError
addError(error: ApplicationError, navigateToErrorPage: boolean = true) {
}
In the provided code, ApplicationError
was expected to be in route.data[0].error
but not in route.data[0]
.
However, TypeScript did not throw any errors, leading to incorrect object types during runtime.
Is there a way to address this issue without manual type checking through instanceof or similar methods? Perhaps some type guard or stricter TypeScript flag like --strictNullCheck?
Coming from a C# background, this behavior was surprising and concerning.
EDIT
Thanks to Saravana, the simple example initially provided works fine.
But when arrays are involved, issues resurface even with noImplictAny = true
.
const myArray = new Array<any>();
myArray[0] = { name: 'test'};
myArray[1] = { name: 1} ;
// TypeScript doesn't complain
this.calc(myArray[0]);
// TypeScript doesn't complain
this.calc(myArray[0].ImActuallyNotPresent);
function calc(x: number) {
console.log(x * 10);
}
I'm confused. Why does this happen?
I understand that it relates to the use of any
, but why does the definition of myArray
override my method's signature?
This inconsistency provides a false sense of security.
Is there a solution to this problem?