microsoft / microsoft/TypeScript

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

Ouverte
#62,146 5 commentaires 4 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Awaiting More Feedback Suggestion
Langage dominant
Go
Étoiles
111k
Forks
14.3k
Merge moyen
2 j 4 h
PR mergées (30 j)
132

Description

🔍 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);

Guide de contribution

Ouvrir le guide de contribution

Par oĂč commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela Ă©vite que deux personnes fassent le mĂȘme travail.
  3. Forkez le dépÎt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Aucun fichier d’implĂ©mentation, test ou point d’entrĂ©e n’est nommĂ©. Commencez par examiner l’opĂ©rateur satisfies existant et le comportement des assertions de type dĂ©crit dans les exemples, puis dĂ©terminez comment une forme de narrowing de is s’intĂ©grerait dans la conception du systĂšme de types du compilateur. C’est terminĂ© lorsque la proposition dispose d’une conception acceptĂ©e et d’un pĂ©rimĂštre d’implĂ©mentation et de tests dĂ©fini.

Rédigé par le modÚle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
typescript
Domaine
compilers
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
PlutĂŽt claire
Accessibilité débutants
30/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.