Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Suggestion: allow type predicates to be inferred when satisfies boolean is present #60778

Closed
@kirkwaiblinger

Description

@kirkwaiblinger

🔍 Search Terms

inferred type predicates, satisfies, return type

✅ Viability Checklist

⭐ Suggestion

I would like to allow type predicates to be inferred when the returned value is constrained by a satisfies boolean expression.
Concretely, I think this code should be legal:

const a: Array<number> = [1, 2, null, 3].filter(x => (x != null) satisfies boolean)

📃 Motivating Example

I am a big fan of explicitly typing any and all function declarations. So, I would never omit the return type on a function like

function isEmptyString(x: unknown): x is '' {
    const rv = x === '';
    return rv;
}

However, with inferred type predicates, it's actually safer to omit the return type, since user-defined type predicates can be totally unsafe:

function isEmptyString(x: unknown): x is '' {
    // whoops
    const rv = x !== '';
    return rv;
}

In other words, the safer code is

function isEmptyString(x: unknown) {
    const rv = x === '';
    return rv;
}

However, this is no longer visually explicit about what it's returning. And what's to stop future-me from making a typo and returning a non-boolean, completely changing the function's applicability.

Therefore, I'd like to be able to write

function isEmptyString(x: unknown) {
   const rv = x === '';
   return rv satisfies boolean;
}

This is both visually clear and easily analyzable by tooling. For example, at typescript-eslint we'd like to implement typescript-eslint/typescript-eslint#9764, but without having an unresolvable conflict with explicit-function-return-type. Allowing a single-return satisfies boolean could be a good way to create a statically analyzable exception for explicit-function-return-type that also allows you to enforce writing boolean-returning functions that otherwise would be syntactically eligible for inferred type predicates to be written without the explicit return type. We have precedent for something similar being familiar to the community in typescript-eslint/typescript-eslint#10231, where a satisfies expression is used to constrain but not change the return type of a function.

💻 Use Cases

  1. What do you want to use this for?
  2. What shortcomings exist with current approaches?
  3. What workarounds are you using in the meantime?
    • Not taking advantage of inferred return types in many cases.

Note - an alternative, more general, approach could be to have a return type syntax like so:

const a: Array<number> = [1, 2, null, 3].filter((x): satisfies boolean => x != null)

This would indicate that the return type is constrained, but will still result in the more specific return type. This might also be useful in cases where a function is passed to a generic, or allowing a single satisfies constraint to apply to multiple return points, like

function returnsOneOrTwo(): satisfies number {
  if (Math.random() > 0.5) {
    return 1;
  } else {
    return 2;
  }
}

However, a) I don't think these are mutually exclusive, and b) the proposed solution does not require new syntax, whereas the alternate solution does.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions