Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using a union type for a rest parameter type annotation #5077

Closed
myitcv opened this issue Oct 2, 2015 · 3 comments
Closed

Using a union type for a rest parameter type annotation #5077

myitcv opened this issue Oct 2, 2015 · 3 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@myitcv
Copy link

myitcv commented Oct 2, 2015

According to the spec (see later in this note), the following should be valid:

function DoIt(...v: number[] | string[]): void {
}

but this gives an error:

A rest parameter must be of an array type

I'm guessing this is therefore an error in the spec?

RestParameter:
   ... BindingIdentifier TypeAnnotation_opt

TypeAnnotation:
   : Type

Type:
   UnionOrIntersectionOrPrimaryType
   FunctionType
   ConstructorType

UnionOrIntersectionOrPrimaryType:
   UnionType
   IntersectionOrPrimaryType

UnionType:
   UnionOrIntersectionOrPrimaryType | IntersectionOrPrimaryType

UnionOrIntersectionOrPrimaryType:
   UnionType
   IntersectionOrPrimaryType

IntersectionOrPrimaryType:
   IntersectionType
   PrimaryType

PrimaryType:
   ParenthesizedType
   PredefinedType
   TypeReference
   ObjectType
   ArrayType
   TupleType
   TypeQuery

ArrayType:
   PrimaryType [no LineTerminator here] [ ]

PredefinedType:
   any
   number
   boolean
   string
   symbol
   void
@RyanCavanaugh RyanCavanaugh added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Oct 2, 2015
@RyanCavanaugh
Copy link
Member

It's a valid grammatical production, but not valid according to the type system. The grammar is about what's syntactically valid, not necessarily semantically valid (the same way that var x: number = 'foo' is allowed by the grammar, but not allowed by the type system).

We perhaps could change the rule from "a rest parameter must be an array type" to "a rest parameter must be an array type or a union type in which all constituents are array types" but that seems not worth adding complexity for, since it's easy enough to add overloads to clarify the intended behavior:

// Either this
function DoIt1(...v: string[]): void;
function DoIt1(...v: number[]): void;
function DoIt1(...v: any[]): void {
}

// Or maybe this is what you meant?
function DoIt2(...v: Array<number|string>): void {
}

@myitcv
Copy link
Author

myitcv commented Oct 2, 2015

It's a valid grammatical production, but not valid according to the type system

Got it, thanks.

but that seems not worth adding complexity for, since it's easy enough to add overloads to clarify the intended behavior

Agreed.

// Or maybe this is what you meant?

No, you understood me correctly!

@mischkl
Copy link

mischkl commented Oct 13, 2016

At least in TS 2.0, you can also write this as follows:

function DoIt(...v: (number | string)[]): void {
}

(discovered in the Protractor type definitions)

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

3 participants