从联合字符串定义yup对象中的键



我有一个字符串联合类型,用作对象中的键。

type Tag = "a" | "b" | "c"
type Obj = { [key in Tag]: number };

我正试着用Yup来做。字符串联合类型是基本的:

const tag = mixed<"a" | "b" | "c">().required();

但是如何在yup对象中使用它作为键呢?

const obj = obj({ [??]: number() });

这是我的解决方案,有点冗长,但看起来对我有用。

import * as yup from "yup";
// generic helper
export type Writable<T> = { -readonly [K in keyof T]: T[K]; };
// key, built as enum
export const tagNames = ["A", "B", "C"] as const;
export type Tag = typeof tagNames[number];
// not readonly names, (easier foor looping on key)
export const writableTagNames = tagNames as Writable<typeof tagNames>;
// your Obj type, keyed with tag.
export type Obj = { [key in Tag]: number };
// your schema that would be the same for all entries
export const tagEntrySchema = yup.number().required("validation.required");
// with its type
export type TagEntrySchemaType = typeof tagEntrySchema;
//now the type of the full shape
export type TagEntryShapeType = { [key in Tag]: TagEntrySchemaType };
// type TagEntryShapeType = {
//     A: RequiredNumberSchema<number | undefined, AnyObject>;
//     B: RequiredNumberSchema<number | undefined, AnyObject>;
//     C: RequiredNumberSchema<...>;
// }
// build an instance of this shape, by looping on keys
export const allShapes: TagEntryShapeType = ((): TagEntryShapeType => {
const result: Partial<TagEntryShapeType> = {};
for (const key of writableTagNames) {
result[key] = tagEntrySchema;
}
return result as TagEntryShapeType;
})();
// and create the yup object from this shape
export const ObjInputSchema = yup.object().shape(allShapes).noUnknown(true);
const candidates = [
{ A: 1, B: 2, C: 3 },
{ A: "romain", B: 2, C: 3 },
{ E: 1, B: 2, C: 3 },
{ A: 1, B: 2 },
];
const TestIt = async (): Promise<void> => {
for (const cadidate of candidates) {
const isvalid = await ObjInputSchema.isValid(cadidate);
console.log((isvalid ? "Valid " : "Invalid ") + JSON.stringify(cadidate, null, 2));
}
};
TestIt();
// Valid {
//   "A": 1,
//   "B": 2,
//   "C": 3
// }
// Invalid {
//   "A": "romain",
//   "B": 2,
//   "C": 3
// }
// Invalid {
//   "E": 1,
//   "B": 2,
//   "C": 3
// }
// Invalid {
//   "A": 1,
//   "B": 2
// }

最新更新