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

Spread operator fails for object type generics #26412

Closed
opiation opened this issue Aug 13, 2018 · 9 comments
Closed

Spread operator fails for object type generics #26412

opiation opened this issue Aug 13, 2018 · 9 comments
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging Help Wanted You can do this
Milestone

Comments

@opiation
Copy link

TypeScript Version: 3.0

Search Terms:
generic, spread, object types, spread types, spread operator

Code

function shallowCopy<T extends object>(state: T): T {
  return {
    ...state
  }
}

Expected behavior:
Should compile as only state's properties are being shallow-copied to the returned result and thus meets the T type.

Actual behavior:
Does not compile with the following error message:

> Spread types may only be created from object types.

If T extends object, is it not then an object type? If not, what type or interface can be defined that is an object type and is not exactly {} or object?

Possible ways forward:

  • If the compiler does not properly recognize T extends object as an object type, perhaps this should be implemented to better support spread/rest operators in modern ecmascript syntax.
  • If T extends object is a recognized object type, the compiler error should be amended to something like "Spread types may only be created from the object type in generics"
  • Silently lock and close this issue adding documentation that states "The spread operator does not support generics extending object"

Playground Link: Contrived example

Related Issues:
#13288 - While this seems like the use case was addressed by @RyanCavanaugh , the resulting workaround suggests far more explicit typing than should be required by the compiler to infer the types in the example provided. While closing that PR might have been the protocol, it seemed more effectively to silence the community request for spread operator support with generics extending from object.

@ghost
Copy link

ghost commented Aug 13, 2018

Duplicate of #24060, #24630, #22687, #20510, #20013.
I'll mark this as an error message bug since we should be providing a message that this doesn't and likely never will work for a type parameter without a cast.

@ghost ghost added Domain: Error Messages The issue relates to error messaging Bug A bug in TypeScript labels Aug 13, 2018
@simonbuchan
Copy link

Just digging through those links, #10727 (comment) suggests that there wasn't a specific reason for this to not work originally, but by #20013 it was decided that this was correct to reject this.

On the one hand, the reasoning there, essentially that own/enumerable requirement for spread isn't modeled by TS, is also an issue even without generics so allowing this usage isn't introducing a new type-safety problem; on the other, the problem is much larger with generics, as the heuristic TS uses for non-generic spreads (which is just strip methods, right?) doesn't work. Is this why #10727 was recently tagged as Revisit?

@alamothe
Copy link

Came here because of:

type A = {
	a: string
	b: number
}

function f<B extends object>(x: A & B) {
	const {a, b, ...other} = x // does not work
}

@oleersoy
Copy link

@RyanCavanaugh RyanCavanaugh added this to the Community milestone Oct 9, 2018
@RyanCavanaugh
Copy link
Member

Silently lock and close this issue

:extremely long sigh:

@Cryrivers
Copy link

Cryrivers commented Oct 16, 2018

Reading #20013, I understand that ...T is not assignable T. But may I know the challenge for getting a correctish type inference?

For example:

type MyObj = {
  a: string,
  b: number,
  c: boolean,
}

function foo<T extends MyObj>(value: T) {
  const { a, ...otherValues } = value;
}

is it possible to infer otherValues as Omit<MyObj, 'a'> & AnyObject, so we can at least make it type-safe if we access properties in otherValues that belongs to MyObj?

Regarding #20013, is it possible to have a helper type RemovePrototype<T> or something?

@xiaodeaux
Copy link

This bug is probably related to #8856 somehow.

@JoshuaKGoldberg
Copy link
Contributor

This no longer gives an error in the latest version: playground link with collected examples from linked issues. Time to close the issue as resolved?

@mnpenner
Copy link

mnpenner commented Mar 9, 2021

@JoshuaKGoldberg Isn't that the problem? It should give a compile-time error ideally.

shallowClone(new C()) doesn't have the method m().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

9 participants