Title: Define a callable TypeScript function with extended prototype
Tags: javascript;typescript;interface
Question: I want to define a callable function foo() (not a class! I don't want to use the new operator here) that will also have a property foo.bar(). In plain JS it will look like this:
function foo() {
// ...
foo.prototype.bar = function bar() {
// ...
I tried it in TypeScript using an interface like this:
interface IFoo {
(): any;
bar(): any;
const foo: IFoo = function(): any {
// ...
foo.prototype.bar = function bar(): any {
// ...
But I get an error:
error TS2322: Type '() =&gt; any' is not assignable to type 'IFoo'.
It seems that TS complains about the intermediate state between defining foo and its property bar, that since foo does not yet have a property bar it cannot be assigned to a const of type IFoo.
How can I fix this?
To ask it in another way: how can I provide an implementation for IFoo?
Comment: @SebastianSebald I don't care that it should be an interface or any other type definition. But I do need a name for that type so I can have variables of that type. The interface in my example describes exactly what I want to do, I just don't know how to provide an implementation for it

Comment: Possible duplicate of [Implementing prototypes for interfaces in TypeScript](http://stackoverflow.com/questions/15340662/implementing-prototypes-for-interfaces-in-typescript)

Comment: Is there a reason for using an interface? If you later on need that interface you can always do `typeof foo`.

Here is the accepted answer: I found a solution using explicit casting
interface IFoo {
(): any;
bar(): any;
// explicit cast
const foo: IFoo = <IFoo&gt;function(): any {
// ...
foo.prototype.bar = function bar(): any {
// ...
I'm not sure that's the best way to do it though...

Here is another answer: If you just want to have foo as a type annotation, you can do something like this:
const foo = function() {};
foo.prototype.bar = function bar() {};
type IFoo = typeof foo;
Comment for this answer: The compiler doesn't seem to recognize and enforce the `prototype.bar` as part of the type. e.g. this compiles without errors: `const foo2: IFoo = function() {};` although the function has no `bar` on its prototype
Comment for this answer: When I try this `const foo3: IFoo = 1;` I get an error: `error TS2322: Type 'number' is not assignable to type '() => void'` which proves that the compiler does not consider `bar` as part of the type.
Comment for this answer: OK, but then it my first example `const foo2: IFoo = function() {};` should also cause a compile error, since there is no `bar` on the prototype of foo2. But it compiles without errors. [see here](https://www.typescriptlang.org/play/index.html#src=const%20foo%20%3D%20function()%20%7B%7D%3B%0D%0Afoo.prototype.bar%20%3D%20function%20bar()%20%7B%7D%3B%0D%0Atype%20IFoo%20%3D%20typeof%20foo%3B%0D%0Aconst%20foo2%3A%20IFoo%20%3D%20function()%20%7B%7D%3B%0D%0Aconsole.log(foo.prototype)%3B%0D%0Aconsole.log(foo2.prototype)%3B)
Comment for this answer: Well, you can not assign a number to an `IFoo` anyway. The compiler might just not show the whole prototype in the error message. You can check out my [example on the playground](https://www.typescriptlang.org/play/#src=const%20foo%20%3D%20function()%20%7B%7D%3B%0D%0Afoo.prototype.bar%20%3D%20function%20bar()%20%7B%7D%3B%0D%0A%0D%0Atype%20IFoo%20%3D%20typeof%20foo%3B%0D%0A%0D%0A%0D%0Aconsole.log(foo.prototype)%3B). The `bar` is correctly added to `foo`.
Comment for this answer: BTW, if you're set something to the `prototype`, it will be avaible when you create an instance. E.g. `foo.bar` is `undefined` but `const myFoo = new foo()` + `myFoo.bar` works.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 2, 'CommentCount': 3, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2017:00:04/25/17', 'FavoriteCount': 0.0, 'PostTypeId': 1, 'Tags': '<javascript><typescript><interface>', 'Title': 'Define a callable TypeScript function with extended prototype', 'ViewCount': 308, 'id': 43613387, 'user_AboutMe': '', 'user_AccountId': 124227.0, 'user_DisplayName': 'Malki', 'user_Reputation': 2285.0, 'user_Views': 252.0, 'user_id': 319182.0}}