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

Can't assign existing property to the rest of generic #28952

Closed
klimashkin opened this issue Dec 11, 2018 · 6 comments
Closed

Can't assign existing property to the rest of generic #28952

klimashkin opened this issue Dec 11, 2018 · 6 comments
Labels
Duplicate An existing issue was already created

Comments

@klimashkin
Copy link

TypeScript Version: 3.2.2 and 3.3.0-dev.20181208

Search Terms:

  • generic
  • pick
  • exclude
  • spread

Code

interface AB {
  a: string;
  b: string;
}

function excludeA<T extends AB>(obj: T) {
  const {a, ...rest} = obj;

  rest.b = '3';

  return rest;
}

excludeA({ a: '1', b: '2', c: 'test' });

Expected behavior:
No errors

Actual behavior:
Property 'b' does not exist on type 'Pick<T, Exclude<keyof T, "a">>'.

Playground Link:
https://www.typescriptlang.org/play/index.html#src=interface%20AB%20%7B%0D%0A%20%20a%3A%20string%3B%0D%0A%20%20b%3A%20string%3B%0D%0A%7D%0D%0A%0D%0Afunction%20excludeA%3CT%20extends%20AB%3E(obj%3A%20T)%20%7B%0D%0A%20%20const%20%7Ba%2C%20...rest%7D%20%3D%20obj%3B%0D%0A%0D%0A%20%20rest.b%20%3D%20'3'%3B%0D%0A%0D%0A%20%20return%20rest%3B%0D%0A%7D%0D%0A%0D%0AexcludeA(%7B%20a%3A%20'1'%2C%20b%3A%20'2'%2C%20c%3A%20'test'%20%7D)%3B

Related
#28821

@weswigham
Copy link
Member

@klimashkin - Consider:

interface AB {
  a: string;
  b: string;
}

function excludeA<T extends AB>(obj: T) {
  const {a, ...rest} = obj;

  rest.b = '3';

  return rest;
}

interface ExactlyAB extends AB {
  a: "a";
  b: "b"
}

declare var exactAB: ExactlyAB;

excludeA(exactAB).b; // claims to be of type "b", but will be the value "3" with your implementation 

@weswigham
Copy link
Member

(But in general yes, #28821 is the reason why the assignment doesn't work, even when you correctly assign a T["b"] - I just wanted to let you know that that code is unsafe from a typesystem perspective, even once that bug is fixed)

@weswigham weswigham added the Duplicate An existing issue was already created label Dec 11, 2018
@que-etc
Copy link

que-etc commented Dec 11, 2018

@weswigham
Does it mean that any reassignment of an object's property, which has a generic type, should be considered invalid?

const test = <T extends {foo: string}>(obj: T): T => {
    // No errors as for v3.2.2
    obj.foo = 'bar';

    return obj;
};

Playground.

@weswigham
Copy link
Member

weswigham commented Dec 12, 2018

Yea - it's a known hole that gets closed when you use indexed access types (which get automatically made when you fetch properties off mapped types). It's quite troublesome, really, since the only reason we haven't fixed it, AFAIK, is for backwards compatibility (and to make mutating patterns "easier" to type).

@typescript-bot
Copy link
Collaborator

This issue has been marked as a duplicate and has seen no activity in the last day. It has been closed for automatic house-keeping purposes.

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

4 participants