Repository: TypeScript
Issue: `satisfies` for return types
Labels: Suggestion,Awaiting More Feedback

### 🔍 Search Terms

satisfies
return

### ✅ Viability Checklist

- [X] This wouldn't be a breaking change in existing TypeScript/JavaScript code
- [X] This wouldn't change the runtime behavior of existing JavaScript code
- [X] This could be implemented without emitting different JS based on the types of the expressions
- [X] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- [X] This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- [X] This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

### <a name="suggestion"></a>⭐ Suggestion

```ts
type AcceptableType = string | number | boolean | undefined | null | object[]

/** `const fn: () => "asdf" | 8 | undefined` */
const fn = (): satisfies AcceptableType => {
  if (someCondition) {
    return "asdf"
  } else if(otherCondition) {
    return 8
  } else {
    return undefined
  }
}
```

### 📃 Motivating Example

```ts
function getResult(): satisfies { a: string, b: number } {
  // type-errors until `satisfies` condition is met
  return {
    // type-hints and type-checking for:
    // (property) a: string
    // (property) b: number
  }
}
```

### 💻 Use Cases

[The `satisfies` operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator) has been immensely useful for ensuring expressions match some wider type while also inferring their narrower type

However, because `satisfies` works only on expressions, getting the same behavior on function return types requires workarounds with several drawbacks. For example, if a function has multiple `return` values, we need to type `satisfies SomeType` for every single one of them, which is not only cumbersome but also prone to human error
```ts
/** `const fn: () => "asdf" | 8 | undefined` */
const fn = () => {
  if (someCondition) {
    return "asdf" satisfies AcceptableType
  } else if(otherCondition) {
    return 8 satisfies AcceptableType
  } else {
    return undefined satisfies AcceptableType
  }
}
```
[playground link](https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEYD2A7AzgF3mpBbEAwqsAJYYmoBc8ARkkhCFCgFCiSwLLpZIYAWIGERSlyVWvUbMWLDAE8ADggCCYMCEUYoNRgBUlCALzYMMEigDm8AD7wUAV1w0htyQyYo3D0SABmFiDAbo4QEG5INABW4BgA2gC6sgD0AFSp8AAG3JjwfijUABQAlPBGAHzwAERQaMB+VW4AHN6+AShBmfCpySw5WPll8CVllQDeLPDwJH7DOPgiYhQopRNTU3AYDjBeNXUN2FDkaAEgaPBqGlo6+oaT8AC+8CAQaAgzhXyCwsRky6v3DYgLY7eAtNBHEgnEhnC7qTTaXQgAzKe5PF5veBrdabbZeHygdpBQ7HU7nS4Im7Iu5TB4sOlAA)

This style is also incompatible with codebases that prefer/require their contributors to declare the return type of their functions (e.g. [through eslint](https://typescript-eslint.io/rules/explicit-function-return-type/))

Another workaround exists by using `satisfies` on the entire function:
```ts
const fn = (() => { /* ... */ }) satisfies () => AcceptableType
```
[playground link](https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEYD2A7AzgF3mpBbEAwqsAJYYmoBc8ARkkhCFCgFCiSwLLpZIYAWIGERSlyVWvUbMWLDAE8ADggCCYMCEUYoNRgBUlCALzYMMEigDm8AD7wUAV1w0htyQyYo3D0SABmFiDAbo4QEG5INABW4BgA2gC6sgD0AFSp8AAG3JjwfijUABQAlPBGAHzwAERQaMB+VW4AHN6+AShBmfCpySw5WPll8IUlZZUA3izw8CR+wzj4ImIUKKWT09NwGA4wXjV1DVPwAL7wIBBoCLOFfILCxGQra0ebINu78E1Hp+eX8OsbLY7Lw+UDtILfFjHUpoKDkNABEBoYalCrwNQaLQ6fSGFhAA)

but having to parenthesize the entire function just to be able to operate on it as an expression and then include the function signature in the `satisfies` type is at best impractical and at worst not even an option, in the case of `function fn() { /* ... */ }` declarations. Of course, function declarations will be available as expressions _after_ the declaration, at which point `satisfies` can be used, but not to its full extent because the type-inference will no longer be able to guide the implementation of the function declaration from within the function body
```ts
// this correctly errors but...
getResult satisfies () => { a: string, b: number }

function getResult() {
  return {
    // you don't get any type-hints or type-checking here
  }
}
```
[playground link](https://www.typescriptlang.org/play/?#code/PTAEBcAsEsGdQMYHsBOKCmDwBsCep01V4AjAV3ADpqAoAc3XACV1YztxRYBDcOAM2itQACgCUoALwA+UAG9Q3AFxdwKaADs6AGlAkVGsgFsShUAF8aNfmQ1ZoSDaAbNW7cOPk1QoDODIoTnLePqAgoLhIZKAAJo4A5Jwuihr44LgADugAtDAa4PCoEJk5CJCYANaadKDlGCGWlkA)

[Being able to specify that the return type of a function `satisfies` a type](#suggestion) would resolve all of the above drawbacks