Reputation: 779
From the TypeScript docs:
// Removes 'optional' attributes from a type's properties
type Concrete<Type> = {
[Property in keyof Type]-?: Type[Property];
};
type MaybeUser = {
id: string;
name?: string;
age?: number;
};
I know I can add the ?
modifier to all properties, what if I want to add it property by property based on a extends
expression?
Something that would behave like this:
// Not valid TypeScript
type Optionalize<T> = {
[P in keyof T](?: T[P] extends SomeInterface): T[P];
}
Upvotes: 2
Views: 1089
Reputation: 779
Relevant GitHub issue: https://github.com/microsoft/TypeScript/issues/32562
NonMatching
Matching
extends infer
techniquetype TestType = {
a: SomeInterface;
b: string;
};
type Intersection<A, B> = A & B extends infer U
? { [P in keyof U]: U[P] }
: never;
type Matching<T, SomeInterface> = {
[K in keyof T]: T[K] extends SomeInterface ? K : never;
}[keyof T];
type NonMatching<T, SomeInterface> = {
[K in keyof T]: T[K] extends SomeInterface ? never : K;
}[keyof T];
type DesiredOutcome = Intersection<
Partial<Pick<TestType, Matching<TestType, SomeInterface>>>,
Required<Pick<TestType, NonMatching<TestType, SomeInterface>>
>
{[K in keyof T]: T[K] extends SomeInterface ? K : never }
it's kind of a workaround to map every matching key to it's own string literal type representation, i.e. given { a: never, b: SomeInterface }
you get { b: 'b' }
, then using indexed access types you get the matching properties in the form of union of string literal types
Upvotes: 2