我有数据库表的以下架构列(用于西瓜数据库)。
const columns = [
{ name: "created_at", type: "number", isOptional: true },
{ name: "created_by", type: "string" },
{ name: "is_corrupt", type: "boolean", isOptional: true },
];
我想创建一个泛型,它将根据上面的示例创建以下类型,我该怎么做?
type ExpectedInferredTypeFromColumns = {
created_at: number | null;
created_by: string;
is_corrupt: boolean | null;
};
我的尝试:
type InferTypeFromColumns<T extends ReadonlyArray<Column>> = {
[K in T extends ReadonlyArray<infer U>
? U extends { name: string }
? U["name"]
: never
: never]: T extends ReadonlyArray<infer U>
? U extends { type: "number"; isOptional: true }
? number | null
: U extends { type: "number" }
? number
: U extends { type: "string"; isOptional: true }
? string | null
: U extends { type: "string" }
? string
: U extends { type: "boolean"; isOptional: true }
? boolean | null
: U extends { type: "boolean" }
? boolean
: never
: never;
};
type MyInferredType = InferTypeFromColumns<typeof columns>;
// Produces: =>
// type MyInferredType = {
// created_at: string | number | boolean | null;
// created_by: string | number | boolean | null;
// is_corrupt: string | number | boolean | null;
// }
正如你所看到的,我的尝试不太符合我的要求ExpectedInferredTypeFromColumns
就这样:操场
const columns = [
{ name: "created_at", type: "number", isOptional: true },
{ name: "created_by", type: "string" },
{ name: "is_corrupt", type: "boolean", isOptional: true },
] as const; // define as const so `columns[number]` gives precise type inference
type Column = {
name: string;
type: "number" | "string" | "boolean"
isOptional?: boolean
}
type TypeMapper = {
boolean: boolean;
string: string;
number: number;
}
// You need to create a union depending if `isOptional` is defined or not
type InferTypeFromColumns<T extends ReadonlyArray<Column>> = {
[K in T[number] as K['name']]: TypeMapper[K['type']] | (K['isOptional'] extends true ? null : never)
}
type Test = InferTypeFromColumns<typeof columns>
/*
type Test = {
created_at: number | null;
created_by: string;
is_corrupt: boolean | null;
}
*/
如果您需要可选键,则需要将可选键和必需键进行交集像这样:
type RequiredInferTypeFromColumns<T extends ReadonlyArray<Column>> = {
[K in T[number] as K['isOptional'] extends true ? never : K['name']]: TypeMapper[K['type']]
}
type OptionalInferTypeFromColumns<T extends ReadonlyArray<Column>> = {
[K in T[number] as K['isOptional'] extends true ? K['name'] : never]?: TypeMapper[K['type']] | null
}
type Intersection<A, B> = A & B extends infer U
? { [P in keyof U]: U[P] }
: never;
type Test = Intersection<RequiredInferTypeFromColumns<typeof columns>, OptionalInferTypeFromColumns<typeof columns>>
/*
type Test = {
created_by: string;
created_at?: number | null | undefined;
is_corrupt?: boolean | null | undefined;
}
*/
这个答案的灵感来自于这个解决方案:有条件申请?每个属性的映射类型中的修饰符
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)