Skip to content

assert type refinements don't work in expressionsΒ #60841

Description

πŸ”Ž Search Terms

  • asserts

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about this

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABAZygJxmA5gCgG4CGANiAKYBci4A1mHAO5gCUlByypaUyihJpiGD1QZsiAN4AoRDMHBEOKAE8ADqTjy+ZRAEIAvIgBEIzFkNMJ02dagALNA0RhS9RABVVpAKJoHaHAAGXgAeatCkACaIBCjopgFMVjIAvpKpkhAIqIj0cGjUPAY4yHAgaBAUVGC0DMyIegB8ltYm2MWl5aSJ1mikUGVIJWUVAHRQcACqKmpoAMJspDiJ6Zlg2QBGvQQF9QpDnZQ0dIwWjc2yqyVEpCNEcLitDx0VTN2yvf1og88341Mz8w4SzSkgyWSg0SIJU2pG2hT2P0O1WOdTOAG0krFRE9hl0ADSY-ajP7TTiAxaJAC6QA

πŸ’» Code

function string(value: unknown): asserts value is string {
    if (typeof value != "string") {
        throw new TypeError(`Expected a string`)
    }
}

const works = (source: unknown) => {
    string(source)
    return source.toUpperCase()
}

const breaks = (source: unknown) => {
    console.log(string(source))
    return source.toUpperCase()
}

const alsobreaks = (source: unknown) => [
    string(source),
    source.toUpperCase()
]```


### πŸ™ Actual behavior

Functions `break` and `alsobreak` do not type check and produce following error: "'source' is of type 'unknown'.", because type refinement produced by function "string" don't seem to apply, if asserting function is not a statement.

### πŸ™‚ Expected behavior

I would expect all three functions to type check, because `string` type refinement should apply to even if refinement is nested in an expression.

### Additional information about the issue

Provided example seems contrived because it was reduced to bare minimum, however there are legitimate uses for refinements like the above [for example](https://www.typescriptlang.org/play/?#code/MYGwhgzhAEBqYCcA8AVaBeaBXAdgaxwHsB3HAPmgG8AoaaAFwE8AHAUwC5ocsQQAfCPQQBLHAHNa0YIRyCEWYPUIIAFAEoqkuvQAWwiADombDFx4hJAX0kBbMPWA6VANzAgsHbPiKk1nV+6s0PrQaDR0dMIAZtAqxqyEMQEe0ACE6Ji6+kYsrBrhEdo6CCRcrMShuQCiCCWqAAbwgdAAJJTJrJbQACaErDBE9FIyUcIINgyEDLmtlFmG8Zb1alrQXawgEEEFhQis9FgIOAzyrKvWdNbW1PGhrOOoprgEJOSmaHxwiKhk1NSgkBgAEkcEMCoJ7MJgNA7A4nPR7jZOChEX5oID7vQYAjxsEYCiHtwbAAje4UHbBGJxXKJBiItIZaAAciJpIQTOgADJOdAAHJYEn3Az6EEIsT3OKo-KrCK6EoVHDlSpsGp1FRMqoADzYilY3XRZkF7JWhQua2o1wBUGgAAVCKIwZIIfQoTD7I4VBBCIdgJ5KNBNZx4MhWWSADTQRhB76hhAUSzSwoAeiT0AM6asFr+KegAEEoJiYMRlHh0cAStbnawbKxQRB-jJBAHTIqKsHqKKDLCPZqVnaHV33U5-ZqI1Hmwm-tQcwARPoDQhDYsIUuiaCsbV7KDCRsN2RDRgtpXt6SyQggVgGECEMQqSSd7tORhqMOSfugwdwlQjziMMe-tYVhWPcm1POQwAdGBMAAbXvD9HxUZ9Xzod96E-D0f0jf9I0A6gAF0-iiXBFB3Y5HAgnBPW9BBfU4Z4fBwRNoD2A4jikHQKKzEChgALyPNtEBA89L2vW8HyHFQeLUPt7XgiTMJ47C+ITIA) when composing set of constraints for later execution.

Activity

  1. MartinJohns commented on Dec 22, 2024

    @MartinJohns
    Contributor

    This is working as intended. See #32695.

  2. typescript-bot commented on Jan 5, 2025

    @typescript-bot
    Contributor

    This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

  3. Gozala commented on Jan 13, 2025

    @Gozala
    Author

    This is working as intended. See #32695.

    Martin Johns (@MartinJohns) mind clarifying a bit what the intended behavior is ? I do see liked PR says

    the call occurs as a top-level expression statement, and

    But then again in works function assertion works as I'd expect even though it's not a top level expression. It could be that behavior matches what PR intended, but I would argue it is all but intuitive, if string function throws on non-string wrapping the call in console.log or array should have not change anything, yet currently it does. So perhaps that was a flaw in intended behavior ?

    Ryan Cavanaugh (@RyanCavanaugh) Mind point what is this issue duplicate of so I can subscribe to updates there ? Thanks

  4. MartinJohns commented on Jan 13, 2025

    @MartinJohns
    Contributor

    But then again in works function assertion works as I'd expect even though it's not a top level expression.

    But it is a top-level expression:

    string(source);

    It's not a nested expression, like in breaks and alsobreaks.

    Mind point what is this issue duplicate of so I can subscribe to updates there ?

    The issue is #32695, which describes that this is as intended. Another related issue would be #53195.

  5. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions