Open pleerock opened 5 years ago
~Okay, I think I found the way it can be implemented right now:~
export type ModelFromSchema<T> = {
[P in keyof T]+?:
T[P] extends MakeItRequired<infer U> ? unknown :
ModelValue<T[P]>
} & {
[P in keyof T]-?:
T[P] extends MakeItRequired<infer U> ? ModelValue<U> :
unknown
}
~Looks like unknown
saves us here.~
~Issue can be closed, but I would like team to pay attention on the scalability of the current approach.~
EDIT 1: No, I was too happy about it. It doesn't work.
EDIT 2: Okay, found a resolution:
type MakeItRequiredKeyNames<T> = { [K in keyof T]: T[K] extends MakeItRequired<infer U> ? K : never }[keyof T];
type MakeItRequiredKeys<T> = Pick<T, MakeItRequiredKeyNames<T>>;
type NonMakeItRequiredKeyNames<T> = { [K in keyof T]: T[K] extends MakeItRequired<infer U> ? never : K }[keyof T];
type NonMakeItRequiredKeys<T> = Pick<T, NonMakeItRequiredKeyNames<T>>;
export type ModelFromSchema<T> = {
[P in keyof NonMakeItRequiredKeys<T>]?:
T[P] extends MakeItRequired<infer U> ? never :
ModelValue<T[P]>
} & {
[P in keyof MakeItRequiredKeys<T>]:
T[P] extends MakeItRequired<infer U> ? ModelValue<U> :
never
}
Just note that your types might look a little "ugly" in the tooltip. It'll still work just fine, though.
If you want to make it look a little better (maybe for debugging or something),
Identity<T> = T;
Merge<T> = (
T extends any ?
Identity<{ [k in keyof T] : T[k] }> :
never
);
Then,
type Blah = Merge<ModelFromSchema<T>>;
When you hover over Blah
, you should see the two objects merged into one
I'm on mobile and can't test it but I think the above works. I'll check again when I get home
Possibly relevant comment from another somewhat related issue (#31581, about detecting such modifiers)
I'd be interested in more streamlined manipulation of modifiers in mapped types. Detecting `readonly` and optional properties is indeed a bunch of hoop jumping, and then if you want to selectively *alter* the modifiers, you need to split the mapping into pieces and intersect them: ```ts type SelectivePartial= Partial > & Required >> extends infer U ? { [P in keyof U]: U[P] } : never; type Foo = SelectivePartial<{ a: string, b: number, c?: boolean }, 'b'> // type Foo = { b?: number | undefined; a: string; c: boolean; } ``` It would be a lot nicer to essentially read and selectively write modifiers inside the mapping directly. (Note the word "selectively"; the [current support](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#improved-control-over-mapped-type-modifiers) for altering modifiers is all-or-nothing ).
Just note that your types might look a little "ugly" in the tooltip. It'll still work just fine, though.
If you want to make it look a little better (maybe for debugging or something),
Identity<T> = T; Merge<T> = ( T extends any ? Identity<{ [k in keyof T] : T[k] }> : never );
Then,
type Blah = Merge<ModelFromSchema<T>>;
When you hover over
Blah
, you should see the two objects merged into oneI'm on mobile and can't test it but I think the above works. I'll check again when I get home
This works, but also seems to turn types like Date
into { toString: () => string, ... }
Would there be a way to prevent this?
As I know there is no way to change property modifier of mapped types based on conditional types. Here is my use case:
My goal is to have
id
non optional, while having others optional. Additional screenshoot from vscode:Can we have this feature?