Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does TypeScript allow overloading return type as 'any' when implementing interfaces

I am trying to determine why TypeScript allows you to overload the return type of a function to the type 'any' from a more specific type when implementing an interface.

In my case I am working in Angular and am injecting the implemented class.

My environment:

Visual Studio 2017

Angular Version 1.5.5

TypeScript Version 2.1.5

The following code compiles without any issue:

export interface IFoo {
    thing: (parameter: number) => string;
}

export class BarService implements IFoo {
    public thing = (parameter: number): any => {
        return { "whatever": parameter };
    }
}
angular.module("FooBar").service("barService", BarService);

So now when I attempt to consume the IFoo interface and am expecting a string to be returned from the 'thing' function call the compiler actually allows it to happen!

export class Whatever {
    public foo: IFoo;
    public myString: string;

    static $inject = ["barService"];
    constructor(barService: IFoo) {

        this.foo = barService;

        this.myString = this.foo.thing(0);
    }
}

It seems that TypeScript should fail to compile when the return type is overloaded with type 'any' because consumers of the interface are expecting a strongly typed object.

like image 959
DNoftsier Avatar asked Sep 20 '26 21:09

DNoftsier


2 Answers

Here is what I have put together.

From https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3.1:

All types in TypeScript are subtypes of a single top type called the Any type. The any keyword references this type. The Any type is the one type that can represent any JavaScript value with no constraints.

And also:

The Any type is used to represent any JavaScript value. A value of the Any type supports the same operations as a value in JavaScript and minimal static type checking is performed for operations on Any values. Specifically, properties of any name can be accessed through an Any value and Any values can be called as functions or constructors with any argument list.

Playing around:

interface IPerson {
    name: string
} 

class Person implements IPerson {
    name: any;
}

// Error
//class Person2 implements IPerson {
//    name: number;
//}

const person: Person = new Person();
person.name = 3;

let x: number = 3;
x = <any>"hello"; // Works!

//x = "hello"; // Error

We can see in even a simple example above that any can be used to override the type system which follows the docs.

My belief is that this behavior is there to allow the flexibility of javascript's untyped (flexible) behavior.

like image 172
Mike Cheel Avatar answered Sep 22 '26 10:09

Mike Cheel


I'm not an expert on Typescript but based on my understanding of any:

https://www.typescriptlang.org/docs/handbook/basic-types.html

We find this comment on that page:

"We want to opt-out of type-checking and let the values pass through compile-time checks."

So I'm guessing when the compilers sees any, it says "I will not confirm this type". Ergo this condition must be sufficient for the compiler to assume that the function has been implemented correctly.

I used to think of any as "accept anything" (which is does). But more precisely it means "Assume this is the type you want.", from what I've seen. So in this case the compiler assumes it is string for your convenience and allows the compile-time check to pass.

like image 43
chrispy Avatar answered Sep 22 '26 12:09

chrispy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!