检查对象是否正确实现了接口

cer*_*lex 7 typescript

界面:

export interface User {
  id: number;
  name: string;
  foo: string;
  bar: string;
}
Run Code Online (Sandbox Code Playgroud)

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

Tit*_*mir 9

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

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

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 
}
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

// 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 
}
Run Code Online (Sandbox Code Playgroud)

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


Jii*_*iiB -8

这是一个例子:

getUser(user: User) {
    return user;
}
Run Code Online (Sandbox Code Playgroud)

只需确保您在函数中传递了 User 类型的用户