microsoft / microsoft/TypeScript

Proposal: repurpose "is" operator for a narrowing version of "satisfies"

Aperta
#62,146 5 commenti 4 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Awaiting More Feedback Suggestion
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
2g 4h
PR unite (30g)
132

Descrizione

🔍 Search Terms

satisfies with narrowing
narrowing literals
satisfias, satisfiesas, sassafras

✅ Viability Checklist
⭐ Suggestion

A narrowing version of the satisfies operator

type Animal = "cat" | "dog";
const animal = "cat" is Animal;
/// ^? = Animal
📃 Motivating Example

Consider an API where the return type is influenced by the input type. For example, this simplification of Tanstack Form (I'm not a contributor to it, but I'm developing something similar).

function useForm<T>(defaultValues: T): T {
    return /*something*/;
}

const values = useForm({
    animal: "cat"
});

The type inferred from animal here is string.

This works fine if animal is a text input in our form, but what if we want it to be an enumeration, e.g. <select>, and also retain some compile-time typechecking? e.g. we want to prevent this

values.animal = "red"

satifies will error if the initial value is not valid, but it doesn't narrow the type:

// #1
const values = useForm({
    animal: "cat" satisfies Animal
});
// typeof values["animal"] = string

as achieves the equivalent of narrowing here, but it masks some errors:

// #2
const values = useForm({
    animal: "red" as Animal // no error
});

I propose to repurpose the existing is keyword. Could use another keyword; bikeshed it later.

const values = useForm({
    animal: "cat" is Animal
});

This would produce a compiler error if the left hand side was not an Animal (like satifies), but additionally narrow the type to Animal.

💻 Use Cases

What shortcomings exist with current approaches?

A more natural flow of the code is disrupted; the field can't be declared inline.

What workarounds are you using in the meantime?

This one is okay, but somewhat disrupts the flow of reading top to bottom.

// #3
const initialAnimal: Animal = "cat";
const values = useForm({
    animal: initialAnimal,
    plainString: "a",
    plainNumber: 1
});

This one requires declaring the entire type separately. Also there may be many more type args than just the data shape. This is the case in Tanstack Form. You'd need useForm<FormValues, Blah, Blah, Blah, ...>;

// #4
type FormValues = {
    animal: Animal
}
const values = useForm<FormValues>({
    animal: "cat"
});

This is probably what I find myself reaching for, but as with #4 requires declaring the entire type

// #5
type FormValues = {
    animal: Animal
    plainString: string
    plainNumber: number
}
const initialValues: FormValues = {
    animal: "cat",
    plainString: "",
    plainNumber: 0
}
const values = useForm(initialValues);

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

Non vengono indicati file di implementazione, test o punti di ingresso. Inizia esaminando l'operatore satisfies esistente e il comportamento delle asserzioni di tipo descritto negli esempi, quindi determina come una forma di narrowing di is si integrerebbe nel design del sistema di tipi del compilatore. Il lavoro è completato quando la proposta dispone di un design accettato e di un ambito definito per implementazione e test.

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.