question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`unknown` isn’t narrowed by assignment

See original GitHub issue

Bug Report

🔎 Search Terms

try block

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about try-catch blocks

⏯ Playground Link

Playground link with relevant code

💻 Code

function f(request: {params: {[param: string]: unknown;}}) {
    let x = request.params.x;
    try {
        x = validate(x);
    } catch (e) {}

    try {
        takesString(x);  // Fails to compile, x is of type unknown.
    } catch (e) {}
}

function validate(x: unknown): string { return ""; }
function takesString(s: string) {}

🙁 Actual behavior

In this example, the code fails to compile because tsc has deduced x in the second block to be of type unknown

🙂 Expected behavior

Since we have successfully exited the first try-catch block, x’s type should be narrowed to string in the second.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
JonathanDCohencommented, Apr 22, 2021

We lose type safety with any. In my case the type of params is used for all of our server’s endpoint handlers, so using unknown is useful to make sure we don’t skip a validation step. I think the true correct way to do this would be to do something like

function validate(x: unknown): x is string {
  // blah blah blah...
}
// ...
function f(request: {params: {[param: string]: unknown;}}) {
    let x = request.params.x;
    if (!validate(x)) { throw SomeError(); }
    // now x is narrowed to `string`
}

which is what I’ve switched to in my code.

1reaction
andrewbranchcommented, Apr 9, 2021

I think this is probably a better example of what you’re surprised by, if I’m understanding you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Show both narrowed type and declared type · Issue #45870 ... - GitHub
This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax ... That an unknown variable does not narrow on assignment is intentional.
Read more >
narrowing types via type guards and assertion functions - 2ality
In other words: The type unknown is too general and we must narrow it. In a way, unknown is also a union type...
Read more >
Typescript: why you should use unknown instead of any
The unknown type, when assigned to a variable, means that a variable type is not known. And typescript doesn't allow you to use...
Read more >
The unknown Type in TypeScript - Marius Schulz
TypeScript 3.0 introduced a new unknown type which is the type-safe ... Here are a few examples of values that we can assign...
Read more >
'unknown' vs. 'any' - typescript - Stack Overflow
... to unknown, but unknown isn't assignable to anything but itself and any without a type assertion or a control flow based narrowing....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found