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

Type information lost after Pick on object with [key: string]: any; #24185

Closed
evollu opened this issue May 17, 2018 · 10 comments
Closed

Type information lost after Pick on object with [key: string]: any; #24185

evollu opened this issue May 17, 2018 · 10 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@evollu
Copy link

evollu commented May 17, 2018

TypeScript Version: 2.8.3

Search Terms: Pick

Code

type X = {
    [key: string]: any;
    x: string,
    y: string
}

type Y = Pick<X, keyof X>

Expected behavior: Y to be same as X

Actual behavior: Y = {[key: string]: any;}

Playground Link:
https://www.typescriptlang.org/play/#src=type%20X%20%3D%20%7B%0D%0A%20%20%20%20%5Bkey%3A%20string%5D%3A%20any%3B%0D%0A%20%20%20%20x%3A%20string%2C%0D%0A%20%20%20%20y%3A%20string%0D%0A%7D%0D%0A%0D%0Atype%20Y%20%3D%20Pick%3CX%2C%20keyof%20X%3E
Related Issues:
My use case is to make a required field optional in type X

type X = {
    [key: string]: any;
    x: string,
    y: string
    ....another 20 params
}

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>; // this works for type without index type
type Y = Omit<X, "x"> & { x?: string}
// expect: x becomes optional and rest remain the same
// actual: y is removed
@Bnaya
Copy link

Bnaya commented May 17, 2018

Its very makes sense it will behave like that,
You can use mapped types if you want to keep type info.
See:

type YY<T> = { [K in keyof T]: T[K] };

type YYY = YY<X>; 

@evollu
Copy link
Author

evollu commented May 17, 2018

@Bnaya yes your solution works for my example. But this issue is causing a problem on Omit. I updated the description with my original use case

my other finding:

// this copies everything
type Y = {
  [P in keyof X]: X[P];
}

// this only copies index type
type Z = keyof X
type Y = {
  [P in Z]: X[P];
}

@mhegazy
Copy link
Contributor

mhegazy commented May 17, 2018

The type has an index signature that allows it to have any string named property.. there are no way int eh language to define exclusion from infinite ranges, e.g. string - "x".. that said, not sure what you expect from Pick rely..

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label May 17, 2018
@evollu
Copy link
Author

evollu commented May 17, 2018

@mhegazy I'm expecting Pick to pick both index signature and extra definition below (y: string and x: string). But now it is only picking index signature

@mhegazy
Copy link
Contributor

mhegazy commented May 17, 2018

keyof X is string| number. string subsumes all the other property names, "x" and "y".

@evollu
Copy link
Author

evollu commented May 17, 2018

is there a way for Typescript to pick "x" and "y" then? Because during type checking, the definition of "x" and "y" takes precedence

@mhegazy
Copy link
Contributor

mhegazy commented May 17, 2018

The compiler will try to keep the properties as long as it can, e.g. Partial<X> does have x and y. the issue is once you get keyof, which is a union, the string subsumes all the other property names, and you end up with only string.
As i noted earlier, it does not make much sense to use operations like Pick, Exclude and Omit on a type like that. if you want to specify the types of properties other than x/y with the index signature, i think you are looking for #17867 instead.

@evollu
Copy link
Author

evollu commented May 17, 2018

will it make sense for keyof to return like string|"x"|"y" so the information will be kept?

my use case is to make one required field optional, which is common for React component with higher order components. The only solutions I can find is to use Extract which doesn't work here.

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants