Reputation: 26467
Let's analyse code snippet below:
class Human {
private name: string;
constructor(name){
this.name = name;
}
}
let h = new Human(5)
Above code doesn't throw any error. And I'd expect it to throw in the constructor call, where I pass 5
.
It seems that constructor's name
parameter gets inferred as any
, where, statically it's easy to find out that I'm assigning it to a private name: string
.
The question is: is there any particular reason that TypeScript is allowing 5
here - or in other words - that name
is inferred as any
, when in this case it's obvious that it has to be a string?
I know I could do another class definition like this:
class Human {
constructor(
private name: string
){}
}
but here I specify the parameter type, so there's no inference here. The same way I could do:
class Human {
private name: string;
constructor(name: string){
this.name = name;
}
}
and there would be no inference either. My question is about inference - why it works this way.
Upvotes: 1
Views: 381
Reputation: 40604
There is a specific compiler option noImplicitAny
specifically to address this. Without "noImplicitAny": true
, your name
is inferred as any
so it does not complain when a number
is passed.
Why it works this way?
Upvotes: 3
Reputation: 2818
I think it's a matter of ambiguity and computational complexity.
First of all, simple rules covering most of the cases are the best. This means the grammar of the language is simple, it's easy to learn it for newcomers and also easy to maintain the compiler itself.
Then, there could be corner cases where inferring a type of an argument by its usage would require a lot of traversing and thus a typo in the code could slow down the compilation.
Also, constructor is a type's external interface which is used by other parts of the application, so it should be explicit for clarity and safety. If your interface implicitly depends on the actual implementation, you can accidentally change something during refactoring and get hard-to-detect bugs.
Upvotes: 0
Reputation: 859
contructor( name ) declaration is equal to constructor( name: any ). Then, this.name = name assignment works seamlessly only because TS is backward-compatible with plain JS: when you assign the 'any' value to a strongly typed var, TS assumes you know what you're doing. So, conversion between number and string stays out of TS control and responsibility.
Upvotes: 2