microsoft / microsoft/TypeScript

Suggesion: Allow recursive/self-references in `satisfies` constraint

Aperta
#54,367 6 commenti 5 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Domain: Something Else Possible Improvement
Lingua principale
Go
Stelle
111k
Fork
14.4k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

Suggestion

🔍 Search Terms

satisfies keyword, recursion, recursive, constraint, self referential

✅ Viability Checklist

My suggestion meets these guidelines:

  • 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.

  • This wouldn't change the runtime behavior of existing JavaScript code

    satisfies only exists during type checking and does not in generated JavaScript

  • This could be implemented without emitting different JS based on the types of the expressions

    As above

  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)

    As above

  • This feature would agree with the rest of TypeScript's Design Goals.

    The same is already possible using a constrained identity function

⭐ Suggestion

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

// 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.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con gli esempi motivanti di satisfies e confronta l’autoreferenza rifiutata con la soluzione basata su una funzione identità vincolata. Determina come dovrebbero comportarsi i vincoli ricorsivi per le dichiarazioni di variabili, quindi verifica che le mappe valide delle macchine a stati siano accettate e che i riferimenti incrociati non validi siano rifiutati senza modificare l’output a runtime.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
30/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.