Skip to content

Type parameters with constraints should be reconstructable #31994

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
zach-waggoner opened this issue Jun 20, 2019 · 2 comments
Closed

Type parameters with constraints should be reconstructable #31994

zach-waggoner opened this issue Jun 20, 2019 · 2 comments

Comments

@zach-waggoner
Copy link

zach-waggoner commented Jun 20, 2019

TypeScript Version: 3.6.0-dev.20190619

Search Terms: type parameter generic constraint assignable instantiated subtype reconstruct

Code

interface AConstraint {
  x: boolean;
}

function fn<A extends AConstraint>(arg: A): A {
  const { x, ...rest } = arg;
  return { x, ...rest };
}

Expected behavior:

pass

Actual behavior:

test.ts:7:3 - error TS2322: Type '{ x: boolean; } & Pick<A, Exclude<keyof A, "x">>' is not assignable to type 'A'.
  '{ x: boolean; } & Pick<A, Exclude<keyof A, "x">>' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype of constraint 'AConstraint'.

It seems like this should work, since { x, ...rest } should be assignable to A regardless of how A is instantiated.

Playground Link:

https://www.typescriptlang.org/play/#src=interface%20AConstraint%20%7B%0D%0A%20%20x%3A%20boolean%3B%0D%0A%7D%0D%0A%0D%0Afunction%20fn%3CA%20extends%20AConstraint%3E(arg%3A%20A)%3A%20A%20%7B%0D%0A%20%20const%20%7B%20x%2C%20...rest%20%7D%20%3D%20arg%3B%0D%0A%20%20return%20%7B%20x%2C%20...rest%20%7D%3B%0D%0A%7D%0D%0A

Related Issues:

#29049

@fatcerberus
Copy link

The error seems correct: you have a constraint on A that it's at least AConstraint so you can work with the value you have as though it's an AConstraint, but you can't actually produce a value of type A because you don't know how specific A actually is. There's no lower bound, so it could be any subtype at all.

For example:

function fn<A extends Animal>(arg: A): A
{
    return new Giraffe("Jeff");  // Giraffe is assignable to Animal, but...
}

let cat = new Cat("Mittens");
let newCat = fn(cat);  // ...we just wanted a cat. :-(

As you point out, in your case you capture ...rest which should cover all the bases in practice--but I think TS is just assuming the worst: A might be never. Then nothing at all would be assignable to it.

@zach-waggoner
Copy link
Author

zach-waggoner commented Jun 20, 2019

That could be. After further digging, I suspect this might be related to #28884. I will close this and defer to that issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants