Q: in Typescript, try...catch error object shows "Object is of type 'unknown'.ts(2571)" router.get('/cells', async (req, res) => {
    try {
      const result = await fs.readFile(fullPath, { encoding: 'utf-8' });
      res.send(JSON.parse(result));
    } catch (err) {
      if (err.code === 'ENOENT') { // Object is of type 'unknown'.ts(2571) (local var) err: unknown
        await fs.writeFile(fullPath, '[]', 'utf-8');
        res.send([]);
      } else {
        throw err;
      }
    }

err.code make this ts error : Object is of type 'unknown'.ts(2571)
I definitely know that err.code exists, so I want to know how to define the type(or interface) of err?
(tsc version info : My global typescript version is v4.3.5 and the above code belongs to my project which has typescript v4.1.2)
--- Edit ---
I finally know why this error happens to me.
I thought I used tsc version under 4.3.x, but it turns out I used v4.4.x.
In vscode, cmd + shift + P and search for Select Typescript version
and I actually used v4.4.3, (I mistakenly thought on version because I only check tsc version from terminal)


Thanks for sharing Youtube video,

A: As stated in other answers, since TypeScript 4.4, errors are automatically cast as unknown, so you can't do anything with them without type checking. Unfortunately ErrnoExceptions are not implemented as an importable class, but rather just a regular Error with additional properties plugged in. It is a type interface in @types/node, but you can't use isinstance to check against it since there's no class definition for this exact error, so checking isinstance against Error will not let you access the err.code property. That being said, you can make the compiler happy with:
OK method
try {
  await fs.readFile(file);
catch (err: NodeJS.ErrnoException) {
  if (err?.code === 'ENOENT') return;
  else throw err;
}

The caveat here is if you simply do if (err.code)... and forget the ?, the compiler won't complain, but you could potentially get a runtime error. This is highly unlikely unless err is null/undefined, but it's still not perfectly type safe since you could forget the ? and get runtime errors in theory. The issue here is you're telling the compiler you know what the error is when in fact the error could be literally anything (which is the motivation to automatically cast errors as unknown).
You could also do catch (err: any) but you won't get any type hints for the codes and you are still subject to the same issues if you forget the use the safe accessor on the code property. There's not a particularly easy way around this since you cannot simply use safe accessor on unknown types like this: if (err?.code === 'ENOENT') return;. I'm not quite sure why and maybe they'll add this in a later realease, but either way, my favorite way to handle these fs errors is to write a typeguard helper function like so:
BEST method
function isErrnoException(e: unknown): e is NodeJS.ErrnoException {
  if ('code' in (e as any)) return true;
  else return false;
}

And then your catch block like this:
try {
  await fs.readFile(file);
} catch (err) {
  // writing err.code here after the typeguard call satisfies the compiler and is SAFE because we already checked the member exists in the guard function.
  if (isErrnoException(err) && err.code === 'ENOENT') return;
  else throw err;
}

This checks at least the error object is ErrnoException-like in that it has a code property. You could get more specific and test that ALL of the ErrnoException properties exist to really make sure it's an ErrnoException.

A: Just very recently, Typescript has been update to make error object inside catch be unknown instead of any
which means, your code looks something like this to your compiler
catch(e: unknown) {
// your logic
}

Provide your own interface and save into another variable to avoid this error:
catch(e : unknown) {
const u = e as YourType
// your logic
}

You can still use any there, but it's not recommended.

A: In JavaScript/TypeScript you can throw anything, not only errors. In theory it could be anything in the catch block. If you want to prevent the type error it could make sense to check if the unknown value is a system error before checking the code.
if (err instanceof SystemError && err.code === 'ENOENT') {
  // file not found
}


A: cast using Record<string, unknown> for the type that you don't know about... so it will be:
const mysteryObject = (unknownObject as Record<string, unknown>)
this message below really helped me and resolved the issue also:


A: in typescript
you can add err : any
ex:
 runInitValidation(_bean: any, _oldVal: any, newVal: any) {
const { validators } = this.props;
if (!validators) return;
try {
  for (let i = 0; i < validators.length; i++) {
    validators[i].validate(newVal);
  }
} catch (err: any) {
  this.errorMessage = err.message;
}

}
