Skip to content

Function rest parameter generic inferenceΒ #45851

Closed

Description

@y-nk

Bug Report

πŸ”Ž Search Terms

Keywords: "rest" "infer"
Found: #45448 which seems slightly related.

πŸ•— Version & Regression Information

  • This is a crash

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type Func1 = (...args: any[]) => void;

const withoutParams1: Func1 = () => {}
const withParams1: Func1 = (a, b, c) => {}

type Func2<T extends any[]> = (...args: T) => void;

const withoutParams2: Func2 = () => {}
const withParams2: Func2 = (a: string, b: string, c: string) => {}

πŸ™ Actual behavior

Func2 type raises error, even though it seems pretty similar to Func1 type.

πŸ™‚ Expected behavior

withoutParams2 at minimum should not throw error, because there's no difference with withoutParams1

Activity

  1. MartinJohns commented on Sep 13, 2021

    @MartinJohns
    Contributor

    Func2 is a generic type with one type-argument. You provided no type-argument. When the type-argument has no default type it must be provided. Docs on generic types

    The error message is quite clear here:

    Generic type ' Func2' requires 1 type argument(s).

    There's no defect here.

  2. IllusionMH commented on Sep 13, 2021

    @IllusionMH
    Contributor

    I guess you confused position of type parameters. If they are used in type alias declaration - you need to use it as Func2<Param>, most likely you wanted to make type parameter as part of function declaration type Func3 = <T extends any[]>(...args: T) => void;
    This will be closer to Func1 but still produce different set of expected errors related to this FAQ.

    Playground

  3. rpidburachynskyi commented on Sep 13, 2021

    @rpidburachynskyi

    I think you can reach similar behaviour with function generics. Like that

    function justFunc<T extends any[]>(fn: Func2<T>) {
    
    }
    
    justFunc((a: string, b: number, c: boolean) => {
    
    })

    Where justFunc can determinate type from first argument, but for types (for variables) you can't do that, because there's two different behaviours behind the single type.

  4. y-nk commented on Sep 14, 2021

    @y-nk
    Author

    thank you Andrii Dieiev (@IllusionMH) KitsoriK for the extended answer with example.

    (ALL) it feels somehow counter intuitive that 1st can work. I totally understand why any[] is not matching undefined in the second example, but the fact that it works in the 1st is at the same time very convenient and weird.

    I would have expected that ...args: any[] expects the type of rest arguments to be array of any, but it seems that undefined also works implicitly.

    It should, in my opinion, have been fn(...args?: any[]) to allow a call with no arguments.

  5. MartinJohns commented on Sep 14, 2021

    @MartinJohns
    Contributor

    It should, in my opinion, have been fn(...args?: any[]) to allow a call with no arguments.

    An optional spread argument makes no sense and is invalid. But fn(...args: any[]) actually is callable without arguments.

    https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABMMAKAdJghgJwOYDOAXIlmAJ4DaAugJSIDeAvgLABQ7Kqt7QA

  6. rpidburachynskyi commented on Sep 14, 2021

    @rpidburachynskyi

    thank you Andrii Dieiev (@IllusionMH) KitsoriK for the extended answer with example.

    (ALL) it feels somehow counter intuitive that 1st can work. I totally understand why any[] is not matching undefined in the second example, but the fact that it works in the 1st is at the same time very convenient and weird.

    I would have expected that ...args: any[] expects the type of rest arguments to be array of any, but it seems that undefined also works implicitly.

    It should, in my opinion, have been fn(...args?: any[]) to allow a call with no arguments.

    FYI, you can assign default values for generic (type Func2<T extends any[] = []> = (...args: T) => void;) and you won't receive errors for const withoutParams2: Func2 = () => {}

  7. y-nk commented on Sep 16, 2021

    @y-nk
    Author

    Martin Johns (@MartinJohns) what i'm pointing out is the lack of consistency between Func1 and Func2 behaviors, which was explained by KitsoriK solution's to set default. but thanks for the constructive comment which just points out what i didn't understand, it really helped πŸ˜“

    KitsoriK that made sense a lot, thank you.

  8. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions