检查对象是否正确实现了接口 [英] Check if object correctly implements interface

查看:32
本文介绍了检查对象是否正确实现了接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

界面:

导出接口用户{身份证号码;名称:字符串;富:字符串;酒吧:字符串;}

如何检查后端返回的对象是否正确实现了用户界面?

解决方案

没有通用的方法来做到这一点.一般的想法是检查对象是否具有预期的属性以及它们是否属于预期的类型.一般来说,如果服务的输出是已知的,我会挑选一些关键的差异来区分输出的类型并只检查那些.

如果没有更多信息,这种情况的方法是:

function isUser(o: any) : o 是用户 {const u: 用户 = oreturn typeof u.id === "number"&&typeof u.name === "string"&&typeof u.foo === "string"&&typeof u.bar === "string";}让 o : any = {};如果(isUser(o)){控制台日志(o.id);//o 是用户}

检查对象是否与所需类型的示例对象具有所有相同属性的更通用方法是:

function is(o: any, sample:T, strict = true, recursive = true) : o is T {if(o == null) 返回假;让 s = 任何样本;//如果我们有原语,我们会检查它们是否属于相同类型并且该类型不是对象if(typeof s === typeof o && typeof o != "object") 返回真;//如果我们有一个数组,那么o数组中的每一项都必须与样本数组中的项属于同一类型if(o instanceof Array){//如果样本不是 arry,那么我们返回 false;if(!(s instanceof Array)) 返回假;让 oneSample = s[0];让 e: 任何;for(e of o) {if(!is(e, oneSample, strict, recursive)) 返回假;}} 别的 {//我们检查样本的所有属性是否都存在于 ofor(let key of Object.getOwnPropertyNames(sample)) {if(typeof o[key] !== typeof s[key]) 返回假;if(recursive && typeof s[key] == "object" && !is(o[key], s[key], strict, recursive)) return false;}//我们检查 o 没有任何额外的属性来采样如果(严格){for(let key of Object.getOwnPropertyNames(o)) {if(s[key] == null) 返回假;}}}返回真;}

示例用法:

//更复杂的接口导出接口用户{身份证号码;名称:字符串;富:字符串;酒吧:字符串;角色: {名称:字符串;身份证号码;}组:数组<{身份证号码,名称:字符串}>;}//从服务返回让 o : 任何 = {角色:{名称:",id:0},电子邮件:[a",b"],组:[ { id: 0, name : ""} ],栏:",foo:",id:0,名称:",};//将检查哪些属性.const 示例用户:用户 = {角色:{名称:",id:0},组:[ { id: 0, name : ""} ],电子邮件:[""],酒吧: "",富:",编号:0,姓名: "",};if(is(o, sampleUser)){控制台日志(o.id);//o 是用户}

注意我没有以广泛的方式测试通用版本,所以期待一些错误和未处理的极端情况,但如果你想走这条路,这应该给你一个良好的开端.>

Interface:

export interface User {
  id: number;
  name: string;
  foo: string;
  bar: string;
}

How do I check that a returned object from backend correctly implements User interface?

解决方案

There isn't general way to do this. The general idea is to check if the object has the expected properties and they are of the expected types. Generally, if the output of the service is known, I would pick a few key differences to distinguish between the types of output and check only those.

Without more information an approach for this case would be:

function isUser(o: any) : o is User {
    const u: User = o 
    return typeof u.id  === "number"
        && typeof u.name === "string"
        && typeof u.foo === "string"
        && typeof u.bar === "string";
}

let o : any = {};
if(isUser(o)) {
    console.log(o.id); // o is User 
}

A more general approach that checks if an object has all the same properties as a sample object of the desired type would be:

function is<T>(o: any, sample:T, strict = true, recursive = true) : o is T {
    if( o == null) return false;
    let s = sample as any;
    // If we have primitives we check that they are of the same type and that type is not object 
    if(typeof s === typeof o && typeof o != "object") return true;

    //If we have an array, then each of the items in the o array must be of the same type as the item in the sample array
    if(o instanceof Array){
        // If the sample was not an arry then we return false;
        if(!(s instanceof Array)) return false;
        let oneSample = s[0];
        let e: any;
        for(e of o) {
            if(!is(e, oneSample, strict, recursive)) return false;
        }
    } else {
        // We check if all the properties of sample are present on o
        for(let key of Object.getOwnPropertyNames(sample)) {
            if(typeof o[key] !== typeof s[key]) return false;
            if(recursive && typeof s[key] == "object" && !is(o[key], s[key], strict, recursive)) return false;
        }
        // We check that o does not have any extra prperties to sample
        if(strict)  {
            for(let key of Object.getOwnPropertyNames(o)) {
                if(s[key] == null) return false;
            }
        }
    }

    return true;
}

Example usage:

// A more complex interface
export interface User {
    id: number;
    name: string;
    foo: string;
    bar: string;
    role: {
        name: string;
        id: number;
    }
    groups: Array<{
        id: number,
        name: string
    }>;
}
// Returned from the service
let o : any = {
    role : { name : "", id: 0 },
    emails: ["a", "b"],
    groups: [ { id: 0, name : ""} ],
    bar: "", foo: "", id: 0, name: "",
};
// What properties will be checked.
const sampleUser: User =  {  
    role : { name : "", id: 0 }, 
    groups: [ { id: 0, name : ""} ],
    emails : [""],
    bar: "", 
    foo: "", 
    id: 0,
    name: "", 
};

if(is(o, sampleUser)){
    console.log(o.id); // o is User 
}

Note I have not tested the generic version in an extensive way, so expect some bugs and unhandled corner cases, but this should give you a good start if you want to go this route.

这篇关于检查对象是否正确实现了接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆