microsoft / microsoft/TypeScript

Suggestion: Automatically infer argument types in overloaded function implementation

Ouverte
#28,172 9 commentaires 31 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.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

Search Terms

infer, arguments, function, overload

Suggestion

For basic container types (Point, Size, Rect, ...) I often write constructors and methods with overloaded signatures so they can be called with the container type itself or with the separate components of the container as arguments. Example:

class Point {
    constructor(point: Point);
    constructor(x: number, y: number);
    constructor(arg1: Point | number, arg2?: number) {
        if (arg1 instanceof Point) {
            this.x = arg1.getX();
            this.y = arg1.getY();
        } else {
            this.x = arg1;
            this.y = arg2!;
        }
    }
}

And I always wonder why I have to specify the argument types in the implementation again when I already defined the possible types in the overload signatures.

In this simple Point type it is still pretty easy but imagine a Rect type which can work with four number arguments, two Point arguments, a Point and Size argument or a Rect argument. Manually writing the combined signature for all these overloaded signatures is cumbersome. And I don't want to use any here because I want type checking in the function body.

An alternative way to write this example is this:

class Point {
    constructor(point: Point);
    constructor(x: number, y: number);
    constructor(...args: [ Point ] | [ number, number ]) {
        const [ arg1, arg2 ] = args;
        // arg1 is now Point | number
        // arg2 is now number | undefined (At least since TS 3.2 because of #27543)
        ...
    }
}

This shows how easy it should be for TypeScript to collect the possible function signatures into a union type so writing constructor(...args) would be enough.

Taking this a step further I even like to write this so I don't need to destructure the arguments myself:

class Point {
    constructor(point: Point);
    constructor(x: number, y: number);
    constructor(arg1, arg2) {
        // arg1 is now Point | number
        // arg2 is now number | undefined
        ...
    }
}

Taking this ANOTHER step further TypeScript could even narrow down the inferred function signatures by each type check done within the function body:

class Point {
    constructor(point: Point);
    constructor(x: number, y: number);
    constructor(arg1, arg2) {
        if (arg1 instanceof Point) {
            // arg2 can now only be `undefined` because the instanceof check removes 
            // the second call signature (where arg1 is a number) from the list of possible 
            // call signatures
            this.x = arg1.getX();
            this.y = arg1.getY();
        } else {
            // arg2 can now only be `number` because the failed instanceof check removes 
            // the first call signature from the list of possible signatures
            this.x = arg1;
            this.y = arg2;
        }
    }
}

I guess the type narrowing is harder to implement but at least the automatic type inference of each argument shouldn't be that hard. So it would be very nice if a future version of TypeScript could do this so using overloading gets a bit easier.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. new expression-level syntax)

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

L'issue ne mentionne aucun fichier ni test. Commencez par suivre la gestion des surcharges et l'inférence des types d'arguments de TypeScript, puis comparez les exemples de Point avec le comportement actuel du compilateur ; le travail est terminé lorsque les implémentations de surcharge peuvent inférer des types de paramètres compatibles tout en conservant la vérification des types et le narrowing dans le corps.

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
25/100

Recevez les nouvelles issues par e-mail

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