Typescript 如何创建一个具有强类型属性的对象,该对象也不允许引用不存在的属性?
标题有点奇怪,但希望我能举例说明 我有一个对象,它包含一组SQL查询(在编译时定义),如下所示:Typescript 如何创建一个具有强类型属性的对象,该对象也不允许引用不存在的属性?,typescript,Typescript,标题有点奇怪,但希望我能举例说明 我有一个对象,它包含一组SQL查询(在编译时定义),如下所示: const queries = { getProductById: { params: { id: 'number' }, sql: `select * from product where id = :id` }, getCustomerById: { params: { id: 'number' }, sql
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 };
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 });
当我需要在另一个文件中使用其中一个查询时,我可以导入查询
对象并通过键引用查询,这是由TypeScript编译器进行类型检查的:
// compiles without issues
db.executeQuery(queries.getProductById, { id: 42 });
// compiler error, because "nonexistentQuery" isn't defined
db.executeQuery(queries.nonexistentQuery, { id: 7 });
现在,我希望能够定义一个接口,将类型安全性添加到我的查询
变量中(在上面的第一个示例中)。首先,我创建了一个带有索引签名的接口:
interface IQueryList {
[queryName: string]: {
params?: { [paramName: string]: string };
sql: string;
};
}
但是,当我将此类型注释添加到我的查询
变量时,我在引用特定查询时会丢失类型安全性:
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 });
在定义我的查询时,是否有一种方法可以同时兼顾类型安全性和引用未在querys
对象上定义的查询时的安全性?
我可以通过使用自己的类型注释标记每个查询来实现这一点,如下所示:
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 };
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 });
但我更愿意避免这种情况,因为每个查询都需要单独标记。此外,没有任何东西可以防止格式不正确的对象包含在最终的查询中。您可以在定义强制约束时使用辅助函数,但在使用查询对象时保持正确检查:
function defineQueries<T extends IQueryList>(q: T) : T {
return q;
}
const queries =defineQueries({
getProductById: {
params: { id: 'number' },
sql: `select * from product where id = :id`
}
});
queries.getProductById; //ok
queries.notAQuery // error
函数定义(q:T):T{
返回q;
}
const querys=definequalies({
getProductById:{
参数:{id:'number'},
sql:`select*from product,其中id=:id`
}
});
querys.getProductById//好啊
querys.notAQuery//错误
没有。鸭子就是鸭子,即使它是一只有三条腿的变异鸭子。另一方面,代理可以帮你做到这一点。但是这样使用它没有多大意义。