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

Union Type made of two types of arrays fails to provide all array's methods #11205

Closed
OleksandrNechai opened this issue Sep 28, 2016 · 7 comments
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Fixed A PR has been merged for this issue Help Wanted You can do this

Comments

@OleksandrNechai
Copy link

TypeScript Version: 1.8.0 / TypeScript playground

Code

let x1: number[];
let x2: number[][];
x1.splice(1, 1); // OK
x2.splice(1, 1); // OK
let x: number[] | number[][];
x.splice(1, 1); // Error: Supplied parameters do not match any signature of call target.

Expected behavior:
TS tutorial states:

If we have a value that has a union type, we can only access members that are common to all types in the union.

Since both x1: number[]; and x2: number[][] have splice method with two params, I expect the union of these two types also to have this method.

Actual behavior:
Compiler reports an error: Supplied parameters do not match any signature of call target. However, it allows using another overload of splice function:

let x: number[] | number[][];
x.splice(1); // OK
@OleksandrNechai
Copy link
Author

It is probably same issue as #10620

@kitsonk
Copy link
Contributor

kitsonk commented Sep 28, 2016

Yes, essentially it is the same, the subtle difference is that when matching the signature, it is matching one that it cannot union the overload:

interface Array<T> {
    splice(start: number): T[];
    splice(start: number, deleteCount: number, ...items: T[]): T[];
}

It cannot union the type of the ...items: T[] argument, therefore it causes an error. Technically if there was anther overload, the code above would work, up until the point where you added arguments that you needed to insert:

interface Array<T> {
    splice(start: number): T[];
    splice(start: number, deleteCount: number): T[];
    splice(start: number, deleteCount: number, ...items: T[]): T[];
}

But it is better to have (number | number[])[] in the first place as mentioned in the issue you referenced.

@OleksandrNechai
Copy link
Author

But it is better to have (number | number[])[] in the first place

Well, then this code does not compile:

let x: (string[] | number[])[]
x.forEach(e => e.splice(1, 1)); // The same error

Unfortunately I have both cases in my code. Whatever way I choose to describe my types I get this error :-(.

@kitsonk
Copy link
Contributor

kitsonk commented Sep 28, 2016

This will work, but I suspect this is not what you want:

let x: (string | number)[][]
x.forEach(e => e.splice(1, 1));

As I suspect you want an array of array of all numbers or an array of arrays of all strings.

The other option would be to help TypeScript along:

let x: (string[] | number[])[];
x.forEach((e: any[]) => e.splice(1, 1));

@OleksandrNechai
Copy link
Author

x.forEach((e: any[]) => e.splice(1, 1)); is pretty neat! Thanks!
I thought transition from C# would be much easier. TS turned out to be very different beast :-)

@kitsonk
Copy link
Contributor

kitsonk commented Sep 28, 2016

TS turned out to be very different beast

You can thank JavaScript for that... Coming from JavaScript to TypeScript (my path) is like finally getting medication to treat your insanity. Coming from C# must be like taking medical marijuana for the first time. Please don't let TypeScript be a gateway drug to the acid trip that is JavaScript though.

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Help Wanted You can do this Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript labels Sep 28, 2016
@RyanCavanaugh
Copy link
Member

I think we should rewrite the signatures to be

interface Array<T> {
    splice(start: number, deleteCount?: number): T[];
    splice(start: number, deleteCount: number, ...items: T[]): T[];
}

with the observation that generic types should have signatures split according to their input use of their type parameters

@RyanCavanaugh RyanCavanaugh reopened this Sep 28, 2016
@mhegazy mhegazy added this to the Community milestone Sep 29, 2016
@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Dec 30, 2016
@mhegazy mhegazy modified the milestones: TypeScript 2.2, Community Dec 30, 2016
@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
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Fixed A PR has been merged for this issue Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

4 participants