microsoft / microsoft/TypeScript

Improve typing of arguments with a function (with respect to overloads)

Open
#28,167 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

In Discussion Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

Search Terms

function overload arguments narrowing

Suggestion

The example is probably the best illustration I can give... It's also much clearer (I think) that the description in text.

Currently, the types of the arguments of a function with overloads cannot be forwarded to another function with the same overloads (1) because the raw typing of the argument doesn't match any of the overloads. But, at the same time, this restriction is not carried out in the relationship between the arguments' types is not used once in the function's body.

We currently have to either assert types (using as) or do if (...) throw with conditions that will never be met runtime.

That requires to sacrifice either type safety or performance.

I've seen #13225. However, my suggestion is more regarding the arguments than the return type. It shouldn't impose any additional restrictions that currently exist (actually, remove some).

Moreover, one of the arguments that was given at the time ("Pass-through overloads are extremely common and would require writing "artificial" code to satisfy the checker") is not true anymore. (See point (1) in the example). I'm not sure if this particular point should be considered a bug in itself or not...

Having the type-system aware of the overloads when typing the arguments could actually restore this.

Use Cases

Simplify overloads implementation and make them more readable.

Examples

let baz: string;

function fn2(foo: 'a', bar: string): void;
function fn2(foo: 'b', bar: number): void;
function fn2(foo: 'a' | 'b', bar: string | number): void
{
    fn(foo, bar); // (1) If this doesn't work, ...
}

function fn(foo: 'a', bar: string): void;
function fn(foo: 'b', bar: number): void;
function fn(foo: 'a' | 'b', bar: string | number): void
{
    if (foo == 'a')
    {
        baz = bar; // (2) ... This should!
    }
}

https://www.typescriptlang.org/play/index.html#src=let%20baz%3A%20string%3B%0D%0A%0D%0Afunction%20fn2(foo%3A%20'a'%2C%20bar%3A%20string)%3A%20void%3B%0D%0Afunction%20fn2(foo%3A%20'b'%2C%20bar%3A%20number)%3A%20void%3B%0D%0Afunction%20fn2(foo%3A%20'a'%20%7C%20'b'%2C%20bar%3A%20string%20%7C%20number)%3A%20void%0D%0A%7B%0D%0A%20%20%20%20fn(foo%2C%20bar)%3B%20%2F%2F%20(1)%20If%20this%20doesn't%20work%2C%20...%0D%0A%7D%0D%0A%0D%0Afunction%20fn(foo%3A%20'a'%2C%20bar%3A%20string)%3A%20void%3B%0D%0Afunction%20fn(foo%3A%20'b'%2C%20bar%3A%20number)%3A%20void%3B%0D%0Afunction%20fn(foo%3A%20'a'%20%7C%20'b'%2C%20bar%3A%20string%20%7C%20number)%3A%20void%0D%0A%7B%0D%0A%20%20%20%20if%20(foo%20%3D%3D%20'a')%0D%0A%20%20%20%20%7B%0D%0A%20%20%20%20%20%20%20%20baz%20%3D%20bar%3B%20%2F%2F%20(2)%20...%20This%20should!%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A

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)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue provides a TypeScript playground example but names no repository files or tests. Start by reproducing the overload implementation and forwarding call, then investigate the checker behavior around overload arguments; done means the forwarding call is accepted and the conditional branch narrows bar to string without assertions or unreachable runtime checks.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.