如果您的验证需求足够复杂,我会评估io-ts 之类的使用情况。它是一个用于根据代码中的元数据自动生成运行时验证的库。
如果您的需求比较有限,您可以利用UserDefined Type Guards。
类型保护的作用是获取unknown(或any,这种函数内部确实没有区别)并告诉编译器传入的对象兼容某个界面。
export interface Field {
icon: string;
text: string;
visibility: boolean;
}
export interface User {
name: Field;
surname: Field;
}
function isField(obj: any): obj is Field {
return (
obj != null &&
typeof obj.icon === "string" &&
typeof obj.text === "string" &&
typeof obj.visibility === "boolean"
);
}
function isUser(obj: any): obj is User {
return obj != null && isField(obj.name) && isField(obj.surname);
// you can get fancy and write something like
// return obj != null && ['name', 'surname'].every(fieldName => isField(obj[fieldName]))
}
// alternative isUser implementation, using a
// prototype. This will give you a compile error is the
// interface is updated, but not this prototype.
const userProto: User = {
name: null,
surname: null
};
function isUserDynamic(obj: any): obj is User {
return obj != null && Object.keys(userProto).every(fieldName => isField(obj[fieldName]));
}
function validateUserArray(obj: any): obj is User[] {
if (obj == null) {
// depending upon the desired approach, you can throw an exception and bail out,
// or simply return false.
throw new Error("The array cannot be null");
}
if (!Array.isArray(obj)) return false;
obj.forEach((user, i) => {
if (!isUser(user))
throw new Error(
`Error at index ${i}: ${JSON.stringify(user)} is not a valid user.`
);
});
return true;
}
const json = `[
{
"name": { "text": "David", "icon": "icon1.png", "visibility": true },
"surname": { "text": "Smith", "icon": "icon2.png", "visibility": true }
},
{
"name": { "text": "Arthur", "icon": "icon3.png", "visibility": true },
"surname": { "text": "L.", "icon": "icon6.png", "visibility": true }
},
{
"name": { "text": "Anthony", "icon": "icon1.png", "visibility": false },
"surname": { "text": "Isaacson", "icon": "icon2.png", "visibility": true }
},
{
"name": { "text": "Mike", "icon": "icon3.png", "visibility": true },
"surname": { "text": "Jobs", "icon": "icon5.png", "visibility": false }
}
]`;
const deserialized: any = JSON.parse(json);
let validatedArray: User[];
if (validateUserArray(deserialized)) {
// here deserialized is a User[], not an any.
validatedArray = deserialized;
}