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

Spreading array into object should not be assignable to array #28801

Closed
AnyhowStep opened this issue Dec 2, 2018 · 6 comments
Closed

Spreading array into object should not be assignable to array #28801

AnyhowStep opened this issue Dec 2, 2018 · 6 comments
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Milestone

Comments

@AnyhowStep
Copy link
Contributor

AnyhowStep commented Dec 2, 2018

TypeScript Version: 3.3.0-dev.20181129

Search Terms: spread array object

Code

const x: number[] = [1, 2, 3, 4];
//Oh, look, a typo.
//Really meant [...x]
//But used     {...x}
const y: number[] = { ...x };

//undefined
console.log(y.length);
//Uncaught TypeError: y.indexOf is not a function
console.log(y.indexOf(3));

Expected behavior:

{ ...x } should not be assignable to number[]

Actual behavior:

{ ...x } is assignable to number[] and results in run-time errors.

Playground Link: here


I actually ran into this problem because I was refactoring some code and decided to use arrays instead of objects. However, I missed a few spots. Luckily, I had unit tests to scream at me.

@ajafff
Copy link
Contributor

ajafff commented Dec 2, 2018

The main problem is that builtin types are declared as interface in lib.xxx.d.ts. If Array was declared as class instead, instance methods would be removed from the spreaded type.

Unfortunately class declarations of the same name are not able to merge, which makes it impossible to add Array.prototype.includes in lib.es2016.array.include.d.ts.

@weswigham weswigham added Bug A bug in TypeScript Needs Investigation This issue needs a team member to investigate its status. labels Dec 4, 2018
@sandersn sandersn added this to the Future milestone Dec 11, 2018
@DanielRosenwasser DanielRosenwasser added Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. and removed Needs Investigation This issue needs a team member to investigate its status. Bug A bug in TypeScript labels Dec 11, 2018
@AnyhowStep
Copy link
Contributor Author

AnyhowStep commented May 25, 2019

I think Event might have a similar problem?

Or MouseEvent, at least.

function foo (evt : MouseEvent) {
    const copy = {...evt};
    console.log(copy.x + 1); //undefined + 1 = NaN
}

@PodaruDragos
Copy link

isn't undefined + 1 = NaN correct ?

@AnyhowStep
Copy link
Contributor Author

The problem is that MouseEvent.x should be a number.

@RyanCavanaugh
Copy link
Member

Tracking at #9726

@emlynmac
Copy link

emlynmac commented Aug 6, 2019

I just ran into this same thing, so created a test code case:

interface IObjectB {
  name: string;
  value: number;
}

interface IObjectA {
  title: string;
  arrayOfThings: IObjectB[];
}

interface IObjectC {
  objectA: IObjectA;
}

const thingThatShouldNotHappen: IObjectC = {
  objectA: {
    arrayOfThings: {
      ...[{ name: "thing", value: 8 }, { name: "otherThing", value: 9 }]
    },
    title: "Test"
  }
};

const thingThatShouldHappen: IObjectC = {
  objectA: {
    arrayOfThings: [
      ...[{ name: "thing", value: 8 }, { name: "otherThing", value: 9 }]
    ],
    title: "Test"
  }
};

console.log(thingThatShouldHappen);
console.log(thingThatShouldNotHappen);

I should get a compile warning on the thingThatShouldNotHappen; I don't. TS 3.5.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

8 participants