【发布时间】:2019-08-03 21:25:24
【问题描述】:
我们最近开始在我们的网络平台项目中使用 typescript。
一个巨大的优势应该是强大的类型系统,它允许在编译时检查各种正确性(假设我们努力正确地建模和声明我们的类型)。
目前,我似乎发现了类型系统所能达到的极限,但似乎不一致,我也可能只是使用了错误的语法。
我正在尝试对我们的应用将从后端接收的对象类型进行建模,并使用类型系统让编译器检查应用中的所有位置:
- 结构,即 TS 编译器只允许对某个类型的对象使用现有(枚举)属性
- 属性类型检查,即 TS 编译器知道每个属性的类型
这是我的方法的最小化版本(或采取direct link to TS playground)
interface DataObject<T extends string> {
fields: {
[key in T]: any // Restrict property keys to finite set of strings
}
}
// Enumerate type's DB field names, shall be used as constants everywhere
// Advantage: Bad DB names because of legacy project can thus be hidden in our app :))
namespace Vehicle {
export enum Fields {
Model = "S_MODEL",
Size = "SIZE2"
}
}
// CORRECT ERROR: Property "SIZE2" is missing
interface Vehicle extends DataObject<Vehicle.Fields> {
fields: {
[Vehicle.Fields.Model]: string,
}
}
// CORRECT ERROR: Property "extra" is not assignable
interface Vehicle2 extends DataObject<Vehicle.Fields> {
fields: {
extra: string
}
}
// NO ERROR: Property extra is now accepted!
interface Vehicle3 extends DataObject<Vehicle.Fields> {
fields: {
[Vehicle.Fields.Model]: string,
[Vehicle.Fields.Size]: number,
extra: string // Should be disallowed!
}
}
为什么第三个接口声明没有抛出错误,而编译器似乎完全能够在第二种情况下禁止无效的属性名称?
【问题讨论】:
标签: typescript types typescript-generics