0

I am having the following code:

try {
 // api call
} catch (error) {
  if (typeof error === 'object' && error !== null && 'message' in error) {
    if (typeof error.message === 'string') {
      if (error.message.match(userRejectedError)) {
        // do stuff
      } else {
        // do other stuff
      }
    }
  }
}

But I am getting the following error: Property 'message' does not exist on type 'object'. Why? I am clearly checking all types needed.

Edit: TSConfig

{
  "compilerOptions": {
    "baseUrl": ".",
    "target": "es6",
    "lib": ["dom", "dom.iterable", "esnext"],
    },
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}
supersize
  • 13,764
  • 18
  • 74
  • 133
  • Doesn't happen to me [here](https://www.typescriptlang.org/play?ts=5.0.4#code/C4JwngBA3gUBEHoEQIYAcCWEDGKA2eMAvjisNgBYQAUApiCAPYgCU0cEGAZjcGGrUY96TEBAC8kiAHJGAIwBWtbMGkQAZOogjmEAIRSAdgFcCGrdIC2tAM42UAc1pqMh7Q2ZtY8eN179BYQ8QADprO0daCSlpG1BXB2kvDh9OHjpgsNt7JzCySmoEABMEFmTU1KQIIsYIOOMuLhSfElo8GyjvCvgqmohGYAp6OuAGpu6iZsn4ScmgA). Can you share a playground with your tsconfig applied? – wonderflame Jun 22 '23 at 08:58
  • @wonderflame updated my OP with the tsconfig. The weird thing is, in my VSCode it does not moan about the linter either. However when running linting, it does. – supersize Jun 22 '23 at 10:12
  • I still can't reproduce:(. Could you make a typescript playground? – wonderflame Jun 22 '23 at 11:03
  • @wonderflame I found the issue. It was due to an older version of TS that didn't support the in operator for checking unknown properties. – supersize Jun 26 '23 at 08:00
  • glad to hear that, let's then close the question – wonderflame Jun 26 '23 at 08:01
  • @wonderflame agreed. – supersize Jun 26 '23 at 08:09

1 Answers1

0

You are not checking type strictly

You are currently just checking that error instance is object, not null, have message as property, and error.message's type name is string, rather than just check error instance is Error type.

use instanceof keyword to check type, not typeof compare with string.

if you can guarantee that error instance is type Error, then ts can surely know that instance have property message.

for example:

try{
/* some error-throwable code... */
} catch(error) {
  /* Use instanceof to compare between instance - type */
  if (error instanceof Error) {
    // Do stuff
  }
  /* Or you can use switch clause */
  switch (error.constructor) {
    case Error:
      // Do stuff
  }
}

below link is type document of Error.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error

Mina-
  • 61
  • 1
  • plus. in switch clause, `.constructor` property only returns true when type is exactly same, no inheritance compare allowed, while instanceof can do. see: https://stackoverflow.com/questions/36332665/how-to-use-instanceof-in-a-switch-statement – Mina- Jun 22 '23 at 10:54
  • the error is not always instance of `Error`. – supersize Jun 22 '23 at 10:55
  • Then, you can add more if/case in bottom to check that type explicitly... – Mina- Jun 22 '23 at 10:59
  • or, What you want is just to guarentee that `error` instance has property `message` and it's type is `string`? – Mina- Jun 22 '23 at 11:00
  • Correct. I want the above code to not throw an error in my linter without coercing types. – supersize Jun 22 '23 at 11:00
  • Then sorry that I can't help anything since I can't reproduce error... – Mina- Jun 22 '23 at 12:56