Closed ijxy closed 6 months ago
Pick<>
is a userland type, there's no special compiler treatment. How would this proposed syntax work in general? How would it change the definition of Pick<>
?
Besides, it's pretty straightforward to create a utility type that helps you, e.g.:
type Data = {
a: number;
b: string;
c: unknown;
d: boolean;
}
type Projection<T, M extends { [key in keyof T]?: string }, K extends keyof T = never> =
{ [P in K]: T[P] } &
{ [P in keyof M as M[P] & string]: P extends keyof T ? T[P] : never }
type Test1 = Projection<Data, { a: "hello-a", b: "goodbye-b" }, "c">
// { c: unknown; "hello-a": number; "goodbye-b": string }
type Test2 = Projection<Data, { a: "hello-a", b: "goodbye-b" }, "a" | "c">
// { a: number; c: unknown; "hello-a": number; "goodbye-b": string }
type Test3 = Projection<Data, { a: "hello-a", b: "goodbye-b" }>
// { "hello-a": number; "goodbye-b": string }
@MartinJohns
Pick<>
is a userland type, there's no special compiler treatment. How would this proposed syntax work in general? How would it change the definition ofPick<>
?Besides, it's pretty straightforward to create a utility type that helps you, e.g.:
You can get very close to what I want with this:
type pick<T, K extends keyof T | [keyof T, string]> = {
[P in K as P extends [keyof T, string] ? P[1] : P]: T[P extends [
keyof T,
string,
]
? P[0]
: P];
};
};
type Test2 = pick<Data, ["a", "hello-a"] | ["b", "hello-b"] | "c">;
// type Test2 = {
// c: unknown;
// "hello-a": number;
// "hello-b": string;
// }
pick<>
as defined is backwards-compatible with the existing Pick<>
, but does not allow for using as
.
I think you'd probably need some compiler special treatment to allow for the as
keyword instead of the tuple.
Introducing new syntax that only works in one generic type isn't really how languages work. This doesn't fit well with anything else and is already accomplishable through other means, as noted above.
🔍 Search Terms
"remap literal keys"
✅ Viability Checklist
⭐ Suggestion
I'd like to be able to use the
as
keyword when usingPick
:📃 Motivating Example
I often find myself remapping fields in third party data and am just getting a bit tired of the very verbose form the definitions for these transformed types usually take, which tends to be combinations of Pick/Omit and intersections.
Perhaps it is just me, but I find these types difficult to grok sometimes--the intersection parts could include types from anywhere, so the complexity jump is potentially enormous.
By contrast, the humble
Pick
statement is simple and easy to understand--it immediately signifies that whatever the new type is, it does not include anything outside the scope of the original type.This is already possible in the context of remapping all keys, such as in:
💻 Use Cases
What do you want to use this for? Remapping individual keys on a type.
What shortcomings exist with current approaches? Using Pick/Omit + intersections works but is more difficult to understand, because in principal the part in the intersection could introduce types outside the scope of the original.
What workarounds are you using in the meantime? Combining
Pick
subtypes with manual remapping, see examples.