如何为TypeScript中具有许多属性的对象提供类型安全性而不忽略类型注释?
我在TypeScript存储库中的问题已被拒绝,并于2020年11月发布。我期望以下API:如何为TypeScript中具有许多属性的对象提供类型安全性而不忽略类型注释?,typescript,Typescript,我在TypeScript存储库中的问题已被拒绝,并于2020年11月发布。我期望以下API: const MarkupPreprocessingDefaultSettings:AsValue={ mustExecuteCodeQualityInspection:正确, 等待其他文件将在以下时间段内保存:1000毫秒, 入口点组相关:{ 缩进空间连续输出代码:2, mustExecuteHTML5_验证:true, mustExecuteAccessibilityInspection:true }
const MarkupPreprocessingDefaultSettings:AsValue={
mustExecuteCodeQualityInspection:正确,
等待其他文件将在以下时间段内保存:1000毫秒,
入口点组相关:{
缩进空间连续输出代码:2,
mustExecuteHTML5_验证:true,
mustExecuteAccessibilityInspection:true
}
};
//同
常量标记重新处理默认设置:{
mustExecuteCodeQualityInspection:正确,
等待其他文件将在以下时间段内保存:1000毫秒,
入口点组相关:{
缩进空间连续输出代码:2,
mustExecuteHTML5_验证:true,
mustExecuteAccessibilityInspection:true
}
} = {
mustExecuteCodeQualityInspection:正确,
等待其他文件将在以下时间段内保存:1000毫秒,
入口点组相关:{
缩进空间连续输出代码:2,
mustExecuteHTML5_验证:true,
mustExecuteAccessibilityInspection:true
}
};
好吧,但现实中我们有什么?
让我们考虑具体的问题。
目标
注释路由
变量,例如:
routing.products
必须工作,但是routing.gibberish
必须抛出TypeScript错误产品
和订单
之外,密钥的计数可以任意大任何
和对象
类型路由={
URN:字符串;
}
常数路由/*:???*/={
产品:{
URN:“/产品”
},
订单:{
URN:“/订单”
}
}
选项1:手动注释所有内容(过量)
结论:非技术性,不易扩展和维护。不能接受
选项2:使用索引类型(松散类型安全性)
结论:它不能防止打字错误;没有可用的自动完成。不可接受。选项3:使用通用辅助函数
这正是您想要的类型,无需您详细说明:
console.log(routing.products.URN); // okay
console.log(routing.orders.URN); // okay
console.log(routing.somethingElse); // compiler error!
// ---------------> ~~~~~~~~~~~~~
// Property 'somethingElse' does not exist
但是,您仍然需要进行所有类型检查,以确保所有属性都是Route
:
const badRouting = asRouting({
products: {
URL: "/product"; // error!
// ~~~~~~~~~~~~~~~~
// Object literal may only specify known properties,
// and 'URL' does not exist in type 'Route'
}
})
我不确定具体的问题是什么。如果问题是“有没有更好的方法来做这件事?”那么我还没有找到一个完美的解决方案。就我个人而言,在项目中,我倾向于容忍发现的问题,但这只是Typescript产生的平衡,更多的类型安全样板。在您的情况下,另一个值得考虑的选择是将其标记为“any”,并在没有typesafety的情况下继续您的旅程。增加问题的风险,但在某些情况下(以及时间/成本预算),这可能是解决问题的方法。谢谢您的回答!请告诉我哪种类型将位于
XXX
const routing:XXX:asRouting({/***})?它属于Record
类型,但您不想手动对其进行注释。我知道TypeScript开发团队不批准“100%的类型必须注释”方法,但我坚持这一点是因为人类的心理原因。然而,我将避免争论我是否应该这样做。
const asRouting = <T extends Record<keyof T, Route>>(t: T) => t;
const routing = asRouting({
products: {
URN: "/products"
},
orders: {
URN: "/orders"
}
});
/* const routing: {
products: {
URN: string;
};
orders: {
URN: string;
};
} */
console.log(routing.products.URN); // okay
console.log(routing.orders.URN); // okay
console.log(routing.somethingElse); // compiler error!
// ---------------> ~~~~~~~~~~~~~
// Property 'somethingElse' does not exist
const badRouting = asRouting({
products: {
URL: "/product"; // error!
// ~~~~~~~~~~~~~~~~
// Object literal may only specify known properties,
// and 'URL' does not exist in type 'Route'
}
})