Repository: TypeScript
Issue: Suggesion: Allow recursive/self-references in `satisfies` constraint
Labels: Possible Improvement

# Suggestion

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->
satisfies keyword, recursion, recursive, constraint, self referential

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code  
  > It would only make previously rejected type assertions possible as it only widens the set of valid type restrictions.
* [x] This wouldn't change the runtime behavior of existing JavaScript code  
  > `satisfies` only exists during type checking and does not in generated JavaScript
* [x] This could be implemented without emitting different JS based on the types of the expressions
  > As above
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  > As above
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).  
  > The same is already possible using a constrained identity function


## ⭐ Suggestion

<!-- A summary of what you'd like to see added or changed -->

It is currently not possible to reference the type of a variable that the `satisfies` constraint is applied on. Enabling this functionality should not be hard, as the same behavior can be recreated using a constrained identity function, see below. This would enable more precise verification of structures by the type checker.

## 📃 Motivating Example

<!--
  If you were announcing this feature in a blog post, what's a short explanation that shows
  a developer why this feature improves the language?
-->

```ts
// I define a (very simplified) state machine by the following type:
type States<S extends string> = Record<S, S>;

// I can then define a map of machine names to their states records:
const myMachines1 = {
  alan: {
    a: "b",
    b: "c",
    c: "c",
  },
  turing: {
    x: "y",
    y: "x",
  },
} satisfies Record<string, States<string>>;

// Problem: This is possible, though should be invalid:
const myMachines2 = {
  foo: {
    a: "x",
  },
  bar: {
    x: "a",
  }
} satisfies Record<string, States<string>>;

// Solution 1: Identity function with self-referential generic:
function defineMachines<T extends {
  [name in keyof T]: States<keyof T[name] & string>;
}>(machines: T) {
  return machines;
}

// Valid:
const myMachines3 = defineMachines({
  alan: {
    a: "b",
    b: "c",
    c: "c",
  },
  turing: {
    x: "y",
    y: "x",
  },
});

// Errors:
const myMachines4 = defineMachines({
  foo: {
    a: "x",
  },
  bar: {
    x: "a",
  }
});

// Solution 2: The same behavior should be achievable using the new `satisfies` keyword:
const myMachines5 = {
  foo: {
    a: "x",
  },
  bar: {
    x: "a",
  }
} satisfies {
  [name in keyof typeof myMachines5]: States<keyof typeof myMachines5[name] & string>;
};
// But errors: Block-scoped variable 'myMachines5' used before its declaration.
```

## 💻 Use Cases

As seen in the example above, this allows for a more precise control over (nested) type restrictions. It is already possible to self-reference type definitions, so why shouldn't this also be possible for variable declarations? The `satisfies` keyword does not modify the type itself to my knowledge.