检查子对象属性是否存在

时间:2019-07-31 18:05:14

标签: typescript

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

# 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))

1 个答案:

答案 0 :(得分:0)

首先,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属性只是不存在。将compileerOption“ 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”逻辑。通过管理输入,我们可以完全跳过检查。