-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Improved control over mapped type modifiers #21919
Conversation
We should talk about this in the next design meeting though. |
Is there any way filter out just the required properties or just the optional properties? I've been trying to make a type mapping that does this with no luck so far. |
@yortus Something like this: type OptionalPropNames<T> = { [P in keyof T]: undefined extends T[P] ? P : never }[keyof T];
type RequiredPropNames<T> = { [P in keyof T]: undefined extends T[P] ? never : P }[keyof T];
type OptionalProps<T> = { [P in OptionalPropNames<T>]: T[P] };
type RequiredProps<T> = { [P in RequiredPropNames<T>]: T[P] };
type Foo = {
a: string;
b: number;
c?: string;
d?: number;
}
type T1 = RequiredProps<Foo>; // { a: string, b: number }
type T2 = OptionalProps<Foo>; // { c?: string | undefined, d?: number | undefined } Strictly speaking this doesn't filter on optional vs. required, but rather whether |
i salute the idea, but somehow this syntax doesn't seem scalable |
@ahejlsberg thanks, that's just what I need. @Aleksey-Bykov the syntax makes me uncomfortable too. TypeScript is steadily building up really useful full compile-time programming capabilities, but some of the syntax seems very specific to a few cases (e.g. this PR). Having a few highly orthogonal compile-time programming constructs that also covered these special cases would be ideal. But I'm sure that's much easier said than done. |
on a constructive note, at some point when there are over 10 different modifiers at play we gonna need some meta syntax to control them, something like this, forgive my french:
or something like |
to extend this idea to mapped or nested types by making a set modifiers a function of the previous/higher set of modifiers
|
These look good to me, and I'm actually pretty OK with the syntax. If something better were suggested, sure, but I'd be comfortable/happy with using this one. As for @Aleksey-Bykov suggestions, compile-time, type-domain functions in general would be a really useful thing to have. Conditional types get us a big step closer to that, but we still aren't there. This might be a nice place to start. |
I think we're making big strides forward. With the pattern matching and recursion, I got a bunch of types to work that just hadn't been possible before (e.g. setting/removing readonly/? recursively in nested structures, flattening promises/arrays). |
Mapped types currently support adding a
readonly
or?
modifier to a mapped property, but they do not provide support the ability to remove modifiers. This matters in homomorphic mapped types (see #12563 and #12826) which by default preserve the modifiers of the underlying type.With this PR we provide the ability for a mapped type to either add or remove a particular modifier. Specifically, a
readonly
or?
property modifier in a mapped type can now be prefixed with either+
or-
to indicate that the modifier should be added or removed.Using this ability, the PR defines a new
Required<T>
type inlib.d.ts
. This type strips?
modifiers from all properties ofT
, thus making all properties required:Some examples of
+
and-
on mapped type modifiers:A modifier with no
+
or-
prefix is the same as a modifier with a+
prefix. So, theReadonlyPartial<T>
type above corresponds toIn
--strictNullChecks
mode, when a homomorphic mapped type removes a?
modifier from a property in the underlying type it also removesundefined
from the type of that property:Fixes #15012.