ducin
ducin

Reputation: 26467

typescript class constructor parameter inferred as any

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

Answers (3)

Saravana
Saravana

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?

See this and this.

Upvotes: 3

Impworks
Impworks

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

JustAndrei
JustAndrei

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

Related Questions