44

I'm reading this section of the TypeScript documentation, under the generic types section, the following two are stated to be the equivalent:

Code Sample 1

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: <T>(arg: T) => T = identity;

Code Sample 2

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: {<T>(arg: T): T} = identity;

The documentation states this is possible due to the following.

We can also write the generic type as a call signature of an object literal type

Despite this line I'm still struggling to understand how the two are equivalent, is there any further documentation or explanation of what it means to be 'a call signature of an object literal type'.

I'm sorry I can't give any further explanation but I'm completely drawing a blank as to how the two are equivalent, to me the second type definition states that myIdentity should be an object?

Thanks.

Flip
  • 6,233
  • 7
  • 46
  • 75
tomhughes
  • 4,597
  • 2
  • 24
  • 33

5 Answers5

22

Functions can have properties, that's what the object literal syntax is for: it allows to define a call signature and additional properties. Your two examples are equivalent because the second doesn't define additional properties on the object literal. You can read more on that in the section on hybrid types.

Additionally, the object literal allows to define multiple call signatures for function overloads. You can create an object of such an interface with Object.assign:

interface Foo {
    (x: string): number,
    (x: number): string,
    bar: Array<any>,
}

const foo: Foo = Object.assign(function (x: any) {
    if (typeof x === 'string') {
        return parseInt(x);
    } else {
        return x.toString();
    }
}, {
    bar: []
});
Tao
  • 2,105
  • 14
  • 15
13

It is because Function in JavaScript is also an object.

Consider the following:

function foo() { return 'foo' }

// vs

const foo = Object.assign(
  function () { return 'foo' },
  {}
)

TypeScript just follows what is possible in JavaScript.

unional
  • 14,651
  • 5
  • 32
  • 56
7

This is implied by the other answers, but may need to be explicit. In short, the second example is a hybrid type between function and object.

https://www.typescriptlang.org/docs/handbook/interfaces.html#hybrid-types

https://www.typescriptlang.org/docs/handbook/2/functions.html#call-signatures

Defining an interface, if you give it a property named "(...)", parentheses without a name, that means your interface can apply to functions. The interface "is" that of a function, so to speak. The hybrid part comes along if you add other, named properties, emphasizing its status as an object.

For some readers, the other answers (which are great) may make more sense after patching this info in.

davo
  • 128
  • 2
  • 7
7

I have exact the same confusion when I read this example in typescript handbook.

Now I understand it like this, but not very sure:

interface MyFunc {
    (arg: string): string //define a function by a call signature
}

let myIdentity: MyFunc
let myIdentity2: { 
    (arg: string): string //here is the body of MyFunc, the call signature
} //the total is a call signature in an object literal type

myIdentity = identity
myIdentity2 = identity

So there are two function definition format:

interface MyFunc {
    (arg: string): string //a call signature
    funcName: (arg: string) => string //express of function in object literal
}
hyyou2010
  • 791
  • 11
  • 22
7

Per as the TypeScript official manual introduced(v3.7),

To describe a function type with an interface, we give the interface a call signature. This is like a function declaration with only the parameter list and return type given.

interface SearchFunc {
    (source: string, subString: string): boolean;
}

You would find that it's exactly how interfaces describe function type, which is in that "object literal" style.

PS: I was skimming the TypeScript official manual and had the same question. When I look into this SO question, all answers were refering to hybrid-type section, in which I didn't find my answer... It roots in the Function-Types section.

Eachann
  • 71
  • 1
  • 2