如何创建具有强类型属性的对象,该对象也不允许引用不存在的属性?

时间:2018-02-27 18:38:03

标签: typescript

标题有点奇怪,但希望我可以通过例子来解释。

我有一个对象,它包含一堆SQL查询(在编译时定义),如下所示:

m/n

当我需要在另一个文件中使用其中一个查询时,我可以const queries = { getProductById: { params: { id: 'number' }, sql: `select * from product where id = :id` }, getCustomerById: { params: { id: 'number' }, sql: `select * from customer where id = :id` } // ... etc ... }; export { queries }; import个对象并按键引用查询,这是由TypeScript编译器进行类型检查的:

queries

现在,我希望能够定义一个接口,为我的// compiles without issues db.executeQuery(queries.getProductById, { id: 42 }); // compiler error, because "nonexistentQuery" isn't defined db.executeQuery(queries.nonexistentQuery, { id: 7 }); 变量添加类型安全性(在上面的第一个示例中)。我首先通过创建一个带索引签名的接口来解决这个问题:

queries

但是,当我将此类型注释添加到我的interface IQueryList { [queryName: string]: { params?: { [paramName: string]: string }; sql: string; }; } 变量时,在引用特定查询时会丢失类型安全性:

queries

有没有办法充分发挥两个方面的作用 - 在定义查询时键入安全性,以及防止引用未在const queries: IQueryList = { getProductById: { params: { id: 'number' }, sql: `select * from product where id = :id` } }; // no compiler error, because "queries" has an index signature db.executeQuery(queries.nonexistentQuery, { id: 12 }); 对象上定义的查询的安全性? < / p>

我可以通过使用自己的类型注释标记每个查询来完成此操作,如下所示:

queries

但我更愿意避免这种情况,因为每个查询都需要单独标记。此外,没有什么可以防止错误形成的对象被包含在最终的interface IQuery { params?: { [paramName: string]: string }; sql: string; } const getProductQuery: IQuery = { params: { id: 'number' }, sql: `select * from product where id = :id` }; const queries = { getProductQuery }; // compiler error, because "nonexistentQuery" doesn't exist db.executeQuery(queries.nonexistentQuery, { id: 12 }); 对象中。

1 个答案:

答案 0 :(得分:3)

在定义强制约束时可以使用辅助函数,但在使用查询对象时保持正确的检查:

public class Animal {
    private String species; // cat or dog
    private int weight; // mass
    private int size; // height

    // getters and setters

    public String getSpecies() {
        return species;
    }

    public void setSpecies(String species) {
        this.species = species;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "species='" + species + '\'' +
                ", weight=" + weight +
                ", size=" + size +
                '}';
    }
}