首页 > 解决方案 > 检查子对象属性是否存在

问题描述

我正在尝试创建检查子类是否具有属性的基类:

# base-filter.ts
export abstract class BaseFilter {
    constructor(
    ) {
    }

    fromObject(filterData: {}, throwOnInvalid = true): BaseFilter {
        for (const [k, v] of Object.entries(filterData)) {
            if (!(k in this)) {
                if (throwOnInvalid) {
                    throw new Error('Filter key ' + k + ' does not exist');
                }
            } else {
                this[k] = k;
            }
        }

        return this;
    }
}

# person-filter.ts
import { BaseFilter } from './base-filter';

export class PersonFilter extends BaseFilter {
    id: number;
    name: string;

    constructor() {
        super();
    }
}

现在设置值:

const personFilter = new PersonFilter();
personFilter.fromObject({
    id: 1,
    foo: 'ahv'
});

'id' 应该通过,'foo' 应该抛出错误。但两者都抛出错误。

我也尝试过,没有雪茄。

if (!this.hasOwnProperty(k))

标签: typescript

解决方案


首先,id:number不分配值,而是键入它。

如果您使用 typescriptlang.org/playground,您可以看到您的PersonFilter类编译为:

// typescript
class PersonFilter extends BaseFilter {
    id: number;
    name: string;

    constructor() {
        super();
    }
}

// compiled javascript
class PersonFilter extends BaseFilter {
    constructor() {
        super();
    }
}

请注意,没有变量分配,id 和 name 属性不存在。将 compilerOption "strictNullChecks" 设置为 true,您的代码将产生编译错误。现在,如果您为这些分配默认属性,您将获得它们的分配:

// typescript
class PersonFilter extends BaseFilter {
    public id: number = undefined;
    public name: string = undefined;

    constructor() {
        super();
    }
}

// compiled javascript
class PersonFilter extends BaseFilter {
    constructor() {
        super();
        this.id = undefined;
        this.name = undefined;
    }
}

以上完成了你所追求的。然而,这并不理想。理想是利用接口。

abstract class BaseFilter {

    constructor() {
        // do nothing
    }

    protected fromObject(filterData: {}): BaseFilter {
        return Object.assign( this, filterData );
    }
}

interface IPersonData {
    id: number;
    name: string;
}

class PersonFilter extends BaseFilter implements IPersonData {

    id: number;
    name: string;

    constructor() {
        super();
    }

    fromObject( filterData:IPersonData ): PersonFilter {
        return super.fromObject( filterData ) as PersonFilter;
    }

}

在这个解决方案中,我们通过输入类型过滤属性,同时仍然重用“fromObject”逻辑。通过管理输入,我们可以完全跳过检查。


推荐阅读