71

I am using typescript to build a microservice and handling signals as well. The code was working fine till a few days ago but recently it started throwing errors. Couldn't find a fix for the issue.

code for handling signals. It is just part of the file. src/main.ts

  enum signals {
    SIGHUP = 1,
    SIGINT = 2,
    SIGTERM = 15
  }
  const shutdown = (signal, value) => {
    logger.warn("shutdown!")
    Db.closeAll()
    process.exit(value)
  }
  Object.values(signals).forEach(signal => {
    process.on(signal, () => {
      logger.warn(`process received a ${signal} signal`)
      shutdown(signal, signals[signal])
    })
  })

When I do ts-node src/main.ts The following error throws and exits.


/home/meraj/.nvm/versions/node/v8.10.0/lib/node_modules/ts-node/src/index.ts:245
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
src/main.ts:35:16 - error TS2769: No overload matches this call.
  The last overload gave the following error.
    Argument of type 'string | signals' is not assignable to parameter of type 'Signals'.
      Type 'string' is not assignable to type 'Signals'.

35     process.on(signal, () => {
                  ~~~~~~

  node_modules/@types/node/base.d.ts:653:9
    653         on(event: Signals, listener: SignalsListener): this;
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The last overload is declared here.

    at createTSError (/home/meraj/.nvm/versions/node/v8.10.0/lib/node_modules/ts-node/src/index.ts:245:12)
    at reportTSError (/home/meraj/.nvm/versions/node/v8.10.0/lib/node_modules/ts-node/src/index.ts:249:19)
    at getOutput (/home/meraj/.nvm/versions/node/v8.10.0/lib/node_modules/ts-node/src/index.ts:362:34)
    at Object.compile (/home/meraj/.nvm/versions/node/v8.10.0/lib/node_modules/ts-node/src/index.ts:395:32)
    at Module.m._compile (/home/meraj/.nvm/versions/node/v8.10.0/lib/node_modules/ts-node/src/index.ts:473:43)
    at Module._extensions..js (module.js:663:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/home/meraj/.nvm/versions/node/v8.10.0/lib/node_modules/ts-node/src/index.ts:476:12)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)

Any fix would be appreciated. Or If you can tell why it was working earlier just 2 days ago and not now.

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
M A SIDDIQUI
  • 2,028
  • 1
  • 19
  • 24
  • Is `process.on()` expecting its first argument to be a number or a string? According to the docs, it looks like it should be a string. `Object.values(signals)` returns an array of numbers. I think you want `Object.keys(signals)`, and I'm guessing what changed in the last two days is you set the enum values to numbers rather than constant strings. – dx_over_dt Sep 20 '19 at 18:20
  • As long as I talk about enum which is not changed for quite a long time, And I thought maybe the number is creating a problem and converted it to string but still did not worked. – M A SIDDIQUI Sep 21 '19 at 08:43
  • Try changing from `Object.values()` to `Object.keys()` – dx_over_dt Sep 21 '19 at 21:46

7 Answers7

25

This sometimes happens when you have passed an incorrect number of arguments to an anonymous function:

    Object.keys(data).reduce((key: string) => {

    }, {}); 

will raise error:

No overload matches this call. Overload 1 of 3

Pass it the correct number of arguments:

    Object.keys(data).reduce((acc: any, key: string) => {
    }, {});
Daniel Viglione
  • 8,014
  • 9
  • 67
  • 101
11

I also had this strange issue, but I worked around it using type assertions (in my case using a string enum):

(Object.values(someEnum) as string[]).concat(otherStringArray);
kitsu.eb
  • 2,996
  • 1
  • 26
  • 28
  • 2
    May you elaborate a bit how you solved it? Maybe you could also help with https://stackoverflow.com/questions/58502778/ please? – B--rian Oct 22 '19 at 11:04
7

Solution 1: Keep numeric enum signals

Object.values(signals)
  // numeric enum includes reverse mapping, filter numbers out and keep "SIGHUP" etc.
  .filter((s): s is NodeJS.Signals => typeof s !== "number") 
  .forEach(signal => {
    process.on(signal, ...) // works now
  })

Solution 2: Use pure signal string literal types

// these string literal items are strongly typed by built-in NodeJS.Signals type
Object.values<NodeJS.Signals>(["SIGHUP", "SIGINT", "SIGTERM"])
  .forEach(signal => {
    process.on(signal, ...) // works now
  })

Solution 3: Change to string enum (no reverse mapping)

enum signals2 {
  SIGHUP = "SIGHUP",
  SIGINT = "SIGINT",
  SIGTERM = "SIGTERM"
}

Object.values(signals2)
  .forEach(signal => {
    process.on(signal, ...) // works now
  })

Why does the error happen?

Numeric enums like signals include a reverse mapping. For example you can do the following:

const r1 = signals.SIGHUP // r1 value: 1
const r2 = signals[signals.SIGINT] // r2 value: "SIGINT"
const r3 = signals[15] // r3 value: "SIGTERM"

That is why you get (string | signals)[] back for Object.values(signals), where string stands for the enum keys and signals for the enum values.

Now, parameter signal in process.on(signal, ...) must be one of the predefined Node.JS string literal types. However we pass in string | signals item type, so TS yells at this point.

Community
  • 1
  • 1
ford04
  • 66,267
  • 20
  • 199
  • 171
1

I got this kind of typescript error when I passed a non-async function to a method that expected an async function.

B T
  • 57,525
  • 34
  • 189
  • 207
0

This happens when you do not assign your types properly.

Your variable data Type MUST match the passing data type.

organizationList: { id: string; name: string;  }[] = [] //if you do this way it type error
organizationList: Organization[] = [] //correct defining method 

get Org() {
    return this.list.filter((org: Organization) => org.id == this.id) //this data type must defined data type
  }
Syscall
  • 19,327
  • 10
  • 37
  • 52
KasunSH
  • 21
  • 2
0

A strange case that happened to me in regards to this kind of error could be for example

somePath = somePath.replace(/\//g, /\\\//g);

use instead

somePath= somePath.replace("/", "\/");
somePath= somePath.replace(/\//, "\/");

because the second argument in replace is of type string.

Igor Micev
  • 1,514
  • 1
  • 17
  • 23
0

In my case below will return error TS2769: No overload matches this call.

Object.values(poll.votes).reduce((sum: number, vote: string) => {
    return sum + vote.length;
  }, 0);

It happens because TypeScript isn't able to infer the type of vote correctly from Object.values(poll.votes), resulting in the error. The solution is set as string[] to Object.values(poll.votes) like below:

(Object.values(poll.votes) as string[]).reduce((sum: number, vote) => {
    return sum + vote.length;
  }, 0);

or another way just create a new variable for Object.values(poll.votes):

  const votes: string[] = Object.values(poll.votes);
  const totalVotes: number = votes.reduce((sum: number, vote) => {
    return sum + vote.length;
  }, 0);
Muhammad Dyas Yaskur
  • 6,914
  • 10
  • 48
  • 73