I have this interface:
export interface MutationSheetDefinition {
_type: "mutation.sheet.definition"
id: string
name: string
mutations: MutationDefinition[]
referencedMutationSheets: MutationSheetReference[]
}
and I want this type:
interface ValidatedMutationSheetDefinition {
name: ValidationOf<string>
mutations: ValidationOf<MutationDefinition>[]
referencedMutationSheets: ValidationOf<MutationSheetReference>[]
}
I know I can pick our a subset of the interface using this:
type narrowed = Pick<MutationSheetDefinition, "name"| "mutations" | "referencedMutationSheets">
which will give me
interface {
name: string
mutations: MutationDefinition[]
referencedMutationSheets: MutationSheetReference[]
}
But can I change the types of the picked keys?
I would settle for a fixed type for all picked keys, so this would do:
interface {
name: Validation
mutations: Validation[]
referencedMutationSheets: Validation[]
}
CodePudding user response:
You can do it like this:
type PickAndChangeToValidationOf<T, P extends keyof T> = {
[K in P]: T[K] extends (infer I)[]
? ValidationOf<I>[]
: ValidationOf<T[K]>
}
I was not sure how you want arrays handled. In your example, you removed the []
and put it behind ValidationOf<T>
. The type above does this too, but only for the first level of arrays. If you want different behaviour for double nested arrays, you should specify so.
Usage:
interface MutationSheetDefinition {
_type: "mutation.sheet.definition"
id: string
name: string
mutations: number[]
referencedMutationSheets: number[]
}
type Narrowed = PickAndChangeToValidationOf<MutationSheetDefinition, "name"| "mutations" | "referencedMutationSheets">
// type Narrowed = {
// name: ValidationOf<string>;
// mutations: ValidationOf<number>[];
// referencedMutationSheets: ValidationOf<number>[];
// }
CodePudding user response:
There you are (I swapped your custom types with random strings, just remove them):
type MutationDefinition = "MutationDefinition";
type MutationSheetReference = "MutationSheetReference";
export interface MutationSheetDefinition {
_type: "mutation.sheet.definition"
id: string
name: string
mutations: MutationDefinition[]
referencedMutationSheets: MutationSheetReference[]
}
type Narrowed = Pick<MutationSheetDefinition, "name"| "mutations" | "referencedMutationSheets">;
type Validation = "Validation";
type Validational<Type> = {
[Property in keyof Type]: Type[Property] extends unknown[] ? Validation[] : Validation;
};
type Definition = Validational<Narrowed>;
const d: Definition = {
name: "Validation",
mutations: ["Validation", "Validation"],
referencedMutationSheets: ["Validation", "Validation"],
}
A drawback of this solution is that it has types hardcoded to only array and all other things. You'll have to add more types if you use any other types, i.e. an array of arrays will need to be added.
CodePudding user response:
type ValidatedMutationSheetDefinition = {
[key in keyof narrowed]: MutationSheetDefinition[key] extends Array<(infer U)> ? Array<ValidationOf<U>> : ValidationOf<narrowed[key]>
}