从 Typescript 界面中选择键并更改它们的类型
Pick keys from a Typescript interface and change their types
我有这个界面:
export interface MutationSheetDefinition {
_type: "mutation.sheet.definition"
id: string
name: string
mutations: MutationDefinition[]
referencedMutationSheets: MutationSheetReference[]
}
我想要这种类型:
interface ValidatedMutationSheetDefinition {
name: ValidationOf<string>
mutations: ValidationOf<MutationDefinition>[]
referencedMutationSheets: ValidationOf<MutationSheetReference>[]
}
我知道我可以使用这个选择界面的子集:
type narrowed = Pick<MutationSheetDefinition, "name"| "mutations" | "referencedMutationSheets">
这会给我
interface {
name: string
mutations: MutationDefinition[]
referencedMutationSheets: MutationSheetReference[]
}
但是我可以更改拾取键的类型吗?
我会为所有选择的键设置一个固定类型,这样就可以了:
interface {
name: Validation
mutations: Validation[]
referencedMutationSheets: Validation[]
}
给你(我用随机字符串交换了你的自定义类型,只需删除它们):
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"],
}
此解决方案的一个缺点是它的类型硬编码为仅数组和所有其他内容。如果您使用任何其他类型,则必须添加更多类型,即需要添加一个数组数组。
你可以这样做:
type PickAndChangeToValidationOf<T, P extends keyof T> = {
[K in P]: T[K] extends (infer I)[]
? ValidationOf<I>[]
: ValidationOf<T[K]>
}
我不确定您希望如何处理数组。在您的示例中,您删除了 []
并将其放在 ValidationOf<T>
后面。上面的类型也这样做,但仅适用于第一级数组。如果你想要双重嵌套数组的不同行为,你应该这样指定。
用法:
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>[];
// }
我有这个界面:
export interface MutationSheetDefinition {
_type: "mutation.sheet.definition"
id: string
name: string
mutations: MutationDefinition[]
referencedMutationSheets: MutationSheetReference[]
}
我想要这种类型:
interface ValidatedMutationSheetDefinition {
name: ValidationOf<string>
mutations: ValidationOf<MutationDefinition>[]
referencedMutationSheets: ValidationOf<MutationSheetReference>[]
}
我知道我可以使用这个选择界面的子集:
type narrowed = Pick<MutationSheetDefinition, "name"| "mutations" | "referencedMutationSheets">
这会给我
interface {
name: string
mutations: MutationDefinition[]
referencedMutationSheets: MutationSheetReference[]
}
但是我可以更改拾取键的类型吗?
我会为所有选择的键设置一个固定类型,这样就可以了:
interface {
name: Validation
mutations: Validation[]
referencedMutationSheets: Validation[]
}
给你(我用随机字符串交换了你的自定义类型,只需删除它们):
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"],
}
此解决方案的一个缺点是它的类型硬编码为仅数组和所有其他内容。如果您使用任何其他类型,则必须添加更多类型,即需要添加一个数组数组。
你可以这样做:
type PickAndChangeToValidationOf<T, P extends keyof T> = {
[K in P]: T[K] extends (infer I)[]
? ValidationOf<I>[]
: ValidationOf<T[K]>
}
我不确定您希望如何处理数组。在您的示例中,您删除了 []
并将其放在 ValidationOf<T>
后面。上面的类型也这样做,但仅适用于第一级数组。如果你想要双重嵌套数组的不同行为,你应该这样指定。
用法:
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>[];
// }