Home > Blockchain >  How to define implementation of function call signatures and construct signatures in typescript
How to define implementation of function call signatures and construct signatures in typescript

Time:09-16

The typescript documentation talks about function call signatures and construct signatures and describes how you can declare the type and use it. https://www.typescriptlang.org/docs/handbook/2/functions.html#call-signatures

call signatures (with no implemetation of a function with type DescribableFunction)

type DescribableFunction = {
  description: string;
  (someArg: number): boolean;
};
function doSomething(fn: DescribableFunction) {
  console.log(fn.description   " returned "   fn(6));
}



construct signatures(with no implementation of a function with type SomeConstructor)

type SomeConstructor = {
  new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
  return new ctor("hello");
}



But it never shows how to define the actual implementation of such functions. And I searched a lot for days, but can't seem to find anything on it. A simple example of each with how to use it and when you would use it would be very helpful in understanding these concepts.
I tried to do it like this of call signatures but obviously its throwing error

type DescribableFunction = {
  description: string;
  (str: string): string;
}

const df: DescribableFunction = {
  description: 'df function description',
  (str: string): {
    return str;
  }
}

console.log(df.description, df('hello world'));

ts playground link

CodePudding user response:

There is no "literal" syntax for declaring a function with extra properties.
But functions are normal objects, and properties can be added to them:

const df: DescribableFunction = (str: string) => {
  return str;
}
df.description = "df function description"

Typically, Typescript would complain that property description is missing in the initial declartion of df, but it looks like it makes an exception for functions, allowing them to be added later on.

As for constructor signatures, they map nicely to the class syntax. Take the following example:

type CacheableConstructor = {
  new(s: string): { x: number };
  cached: boolean
};

It can be implemented like this:

class SomeCC {
  static cached = false
  x: number
  constructor(s: string) {}
}

// check that if matches the constructor signaure
const cc: CacheableConstructor = SomeCC

CodePudding user response:

Actually, Object.assign has a signature that returns an interection type of its arguments

Object.assign<T,U>( t: T, u: U ) : T & U 

it could be then just

type DescribableFunction = {
  description: string;
  (str: string): string;
}

const df: DescribableFunction = Object.assign( 
    (str: string) => str,
    { description: 'df function description' },
);

console.log(df.description, df('hello world'));
// works

This has a drawback, it only works when you assign the description to the function and not the other way around, although TypeScript types both.

// types correctly but doesn't work (for obvious reason)
type DescribableFunction = {
  description: string;
  (str: string): string;
}

const df: DescribableFunction = Object.assign( 
    { description: 'df function description' },
    (str: string) => str,
);

console.log(df.description, df('hello world'));
// df is not a function

CodePudding user response:

I did not know this myself, but the compiler will actually check that you set the description property after creating the function:

type DescribableFunction = {
  description: string;
  (str: string): string;
}

const df: DescribableFunction = (str: string) => {
  return str;
}

// if you comment out the following line, the compiler will complain
df.description = 'df function description',

console.log(df.description, df('hello world'));

TS Playground

  • Related