Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flag to change catch variables' default types to unknown #41013

Merged
merged 9 commits into from
Jun 3, 2021

Conversation

DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Oct 9, 2020

This change adds a new flag called useUnknownInCatchVariables which changes the default type of catch clause variables from any (today's existing behavior) to unknown.

More specifically, under this flag, the following code

try {
  // ...
}
catch (err) {
  console.log(err.message);
}

would become equivalent to

try {
  // ...
}
catch (err: unknown) {
  console.log(err.message); // error: Property 'message' does not exist on type 'unknown'.
}

As a result, a user would receive the following error message from TypeScript:

Property 'message' does not exist on type 'unknown'.

To mitigate this, a user could explicitly perform runtime checks

try {
  // ...
}
catch (err) {
  // First check if we have an Error
  if (err instanceof Error) {
    console.log(err.message);
  }
}

or if that is too painful, a user could use a type assertion to any, or provide an explicit annotation on the catch clause variable with the type any to revert to the old default behavior.

try {
  // ...
}
catch (err: any) {
  console.log(err.message);
}

Fixes #41016.

@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Oct 9, 2020
@DanielRosenwasser DanielRosenwasser changed the title 'unknown' in catch variables --useUnknownInCatchVariables Oct 9, 2020
@DanielRosenwasser DanielRosenwasser changed the title --useUnknownInCatchVariables Add flag to change 'catch' variable default to 'unknown' Oct 9, 2020
@DanielRosenwasser DanielRosenwasser marked this pull request as ready for review October 9, 2020 21:10
@sandersn sandersn added the Experiment A fork with an experimental idea which might not make it into master label Oct 20, 2020
@typescript-bot
Copy link
Collaborator

The TypeScript team hasn't accepted the linked issue #41016. If you can get it accepted, this PR will have a better chance of being reviewed.

@johnnyreilly
Copy link

johnnyreilly commented Feb 10, 2021

It would be awesome if strict also enabled this flag; is that likely? (It's possible that this change does that already; but I'm on my phone so it's hard to tell 😅)

@DanielRosenwasser
Copy link
Member Author

@typescript-bot pack this
@typescript-bot test this
@typescript-bot user test this
@typescript-bot run dt
@typescript-bot perf test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 5, 2021

Heya @DanielRosenwasser, I've started to run the extended test suite on this PR at a32013b. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 5, 2021

Heya @DanielRosenwasser, I've started to run the parallelized Definitely Typed test suite on this PR at a32013b. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 5, 2021

Heya @DanielRosenwasser, I've started to run the parallelized community code test suite on this PR at a32013b. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 5, 2021

Heya @DanielRosenwasser, I've started to run the perf test suite on this PR at a32013b. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 5, 2021

Heya @DanielRosenwasser, I've started to run the tarball bundle task on this PR at a32013b. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 5, 2021

Hey @DanielRosenwasser, I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
    "devDependencies": {
        "typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/102337/artifacts?artifactName=tgz&fileId=CB39C963580F3F2B857D3171C4A6770212DE0222B86B618B209B2F4B2E12A36B02&fileName=/typescript-4.3.0-insiders.20210505.tgz"
    }
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/[email protected]".;

Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commandLineParser entry should make the new flag a strict one, I think.

src/compiler/commandLineParser.ts Outdated Show resolved Hide resolved
@@ -0,0 +1,35 @@
// @useUnknownInCatchVariables: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

except for this, I'm not convinced we even need a new test, since we know that unknown narrows, and from some other tests, that strict changes the type of the catch variable to unknown.

I guess there's nothing to change here, except possibly dropping the narrowing tests from this test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added that style of code in because most of the purpose of this feature is to ensure that catch variables are narrowed, and that we error on usages if a user doesn't do so.

@gvanrossum
Copy link

Meta: I was confused by the initial comment, because I wasn't familiar with unknown. I'd say that the first snippet, with catch (err) should not have a comment indicating the error (because IIUC without the new flag it doesn't produce an error), and the second snippet, with explicit catch (err: unknown) should have the error comment, because even without the new flag that's an error. (Right?)

@DanielRosenwasser
Copy link
Member Author

@gvanrossum good call, thanks! Must have been an earlier copy/paste error.

Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼 Does what we talked about in the design meeting.

Side note: It's a little worrying that we don't already have more tests with both (1) catch and (2) strict: true.

@DanielRosenwasser DanielRosenwasser merged commit 9906092 into main Jun 3, 2021
@DanielRosenwasser DanielRosenwasser deleted the unknownInCatchVariables branch June 3, 2021 20:13
@DanielRosenwasser DanielRosenwasser added the Breaking Change Would introduce errors in existing code label Jun 3, 2021
rekmarks added a commit to MetaMask/eslint-config that referenced this pull request Aug 30, 2021
Fixes the `no-throw-literal` rule configuration for TypeScript by enabling the appropriate rule in the TypeScript config, per [documentation](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-throw-literal.md#how-to-use).

This is timely due to recent [changes to TypeScript](microsoft/TypeScript#41013).
nightah added a commit to authelia/authelia that referenced this pull request Sep 2, 2021
Typescript 4.x changes the default behaviour of try catch and its err type from `any` to [`unknown`](microsoft/TypeScript#41013).

This change ensures that where we rely on said variable it is cast accordingly as an `Error`.
nightah added a commit to authelia/authelia that referenced this pull request Sep 4, 2021
* build(deps): update dependency typescript to v4.4.2

* fix(web): cast try catch err type to error

Typescript 4.x changes the default behaviour of try catch and its err type from `any` to [`unknown`](microsoft/TypeScript#41013).

This change ensures that where we rely on said variable it is cast accordingly as an `Error`.

Co-authored-by: Renovate Bot <[email protected]>
Co-authored-by: Amir Zarrinkafsh <[email protected]>
@pvinis
Copy link

pvinis commented Sep 23, 2021

Is there a way to type a function that it throws specific types? So that catch could know what to expect.

Like a func that can throw MyError, and then catch knows that e is MyError.

@DanielRosenwasser
Copy link
Member Author

Should the flag useUnknownInCatchVariables also affect the return type of Promise.prototype.catch?

@guilhermesimoes #45602 proposes that idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Breaking Change Would introduce errors in existing code For Milestone Bug PRs that fix a bug with a specific milestone
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Flag to type 'catch' variables as 'unknown'.
7 participants