typescript - 检查对象是否正确实现接口(interface)

标签 typescript

接口(interface):

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

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

最佳答案

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

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

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 
}

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

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;
}

示例用法:

// 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 
}

注意我没有广泛测试通用版本,所以可能会出现一些错误和未处理的特殊情况,但如果您想走这条路,这应该会给您一个良好的开端。

关于typescript - 检查对象是否正确实现接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48442746/

相关文章:

node.js - 处理ExpressJS中混合的同步和异步错误的最佳方法

javascript - 如何为 TypeORM 指定 ormconfig.ts?

typescript - typescript 和输出 javascript 文件的解决方案资源管理器 View

typescript - RxJs ErrorObservable 的重大变化(迁移 5 -> 6)

node.js - tslint 方法返回类型文档

Angular 单元测试 : Using Generics to Create Component

javascript - React TypeScript Cheatsheet 的门户示例代码似乎已损坏

typescript - 在 Visual Studio 中使用 angular2

angular - 如何限制 NgSelect 下拉面板中显示的项目数?

angular - 如何在 Angular Dart 中使用 Angular Material 表