镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Generic type constraint does not apply to rest parameters #2328

Description

The following fails to compile even though T is constrained to an array type:

function attach<T extends any[]>(cb: (...args: T) => void): void { }
A rest parameter must be of an array type.
(parameter) args: T extends any[]

Activity

  1. danquirk commented on Mar 12, 2015

    @danquirk
    Member

    This is technically by design but it's a reasonable suggestion. We also don't allow subtypes of array without generics.

  2. RyanCavanaugh commented on Mar 17, 2015

    @RyanCavanaugh
    Member

    Spec section 3.8.2.2

  3. added
    By DesignDeprecated - use "Working as Intended" or "Design Limitation" instead
    and removed
    SuggestionAn idea for TypeScript
    on May 4, 2015
  4. RyanCavanaugh commented on May 4, 2015

    @RyanCavanaugh
    Member

    This doesn't actually make sense.

    The function should be rewritten this way:

    function attach<T>(cb: (...args: T[]) => void): void { }

    Any production that requires that you write T instead of T[] would require a lie, because the type of the rest arg is always going to be the basic Array type, not some subtype thereof. It would be especially dangerous to flow that type through.

  5. JoshuaKGoldberg commented on Sep 8, 2016

    @JoshuaKGoldberg
    Contributor

    Ryan Cavanaugh (@RyanCavanaugh) what if the function is meant to be used like the following?

    attach((age: number, name: string) => {
        console.log({ age, name });
    });
    
    // written explicitly:
    attach<[number, string]>(/*... */);

    Using the ...args: T[] approach we would then have this typed as (number | string)[] instead of [number, string] right?

  6. RyanCavanaugh commented on Sep 8, 2016

    @RyanCavanaugh
    Member

    If that's the desired behavior you'd be better off writing some explicit overloads e.g. https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/underscore/underscore.d.ts#L1126

  7. ds300 commented on Jun 25, 2017

    @ds300

    As a library author this makes me sad, since with overloading you lose the parameter name information. Plus it produces ugly inline documentation.

  8. YoshiWalsh commented on Jan 12, 2018

    @YoshiWalsh

    I'd love to see this decision reconsidered. As I understand it, one of TypeScript's major design goals is to have a type system flexible enough to represent any common JavaScript design pattern. Rest parameters have been supported for years, and generics are a vital part of TypeScript, the fact that you can't use both together is unfortunate.

  9. theRobinator commented on Apr 4, 2018

    @theRobinator

    I'd also like to be able to use this feature. I'm building an abstract command pattern class that I'd like to do something like this for:

    abstract class Command<T extends any[]> {
        public load(...args: T);
        public loadIfNeeded(...args: T);
        public clearAndReload(...args: T);
    }
    

    Requiring implementing classes to override every method in the abstract class just to provide a type definition is ugly. Implementing this issue's feature would solve this nicely.

  10. locked and limited conversation to collaborators on Jul 25, 2018
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

    By DesignDeprecated - use "Working as Intended" or "Design Limitation" instead

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions