Skip to content

Function argument with object rest spread generates wrong type error #25217

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

Closed
zamb3zi opened this issue Jun 26, 2018 · 4 comments
Closed

Function argument with object rest spread generates wrong type error #25217

zamb3zi opened this issue Jun 26, 2018 · 4 comments
Assignees
Labels
Duplicate An existing issue was already created

Comments

@zamb3zi
Copy link

zamb3zi commented Jun 26, 2018

TypeScript Version: 2.9.1-insiders.20180525

Search Terms: argument rest spread object

Code

const f = (options: { foo?: number }) => { };
let o: {
    foo?: number;
    bar?: string
} = {};
f(o); // ok
f({ ...o }); // error: bar does not exist in type { foo?: number }.
f({ ...o, foo: 5 }); // same error. this is the use case.
let p = { ...o };
f(p); // ok
f(p = { ...o, foo: 5 }); // also ok

Expected behavior:

{...o} has the same type as o and should be interchangeable as function argument.

Actual behavior:

Incorrect error is generated.

Playground Link:

Playground

Related Issues:

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Jun 26, 2018

@sandersn please apply the appropriate label to this issue 👍

@sandersn
Copy link
Member

Duplicate of #19775

Probably won't be fixed until we have exact types, because people who don't want excess property errors currently have two workarounds (a [deprecated] compiler flag and extract-local), but people who do want excess property errors would have no way to cause them if this bug is fixed.

@sandersn sandersn added the Duplicate An existing issue was already created label Jun 26, 2018
@zamb3zi
Copy link
Author

zamb3zi commented Jun 27, 2018

Thanks a lot and sorry I couldn't find the duplicate. For anyone else landing here, some workarounds are:

const f = <O extends { foo?: number }>(options: O) => { };

OR

const f = (options: { foo?: number }) => { };
const ignoreExcess = <T>(arg: T) => arg;
let o: {
    foo?: number;
    bar?: string
} = {};
f(ignoreExcess({ ...o, foo: 5 })); // ok

@sandersn
Copy link
Member

You can also do

const f = (options: { foo?: number }) => { };
let o: {
    foo?: number;
    bar?: string
} = {};
const ignoreExcess = { ...o, foo: 5 };
f(ignoreExcess); // ok

Which is probably cheaper at runtime, depending on how much the VM tries to optimise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants