Недавно мы начали использовать машинописный текст для наших проектов веб-платформ.
Предполагалось, что одним из значительных преимуществ будет мощная система ввода, которая позволяет проверять правильность всех типов во время компиляции (при условии, что мыприложить усилия для того, чтобы смоделировать и объявить наши типы должным образом).
В настоящее время я, кажется, нашел пределы того, что может достичь система типов, но это кажется непоследовательным, и я также могу просто использовать неправильносинтаксис.
Я пытаюсь смоделировать типы объектов, которые наше приложение будет получать из серверной части, и использовать систему типов, чтобы компилятор проверял всюду в приложении:
- структура, т. Е. Только существующие (перечисляемые) свойства разрешены компилятором TS для объектов типа
- проверки типов свойств, т.е. тип каждого свойства известен компилятору TS
Вот минимизированная версия моего подхода (или прямая ссылка на игровую площадку TS )
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!
}
}
Почему третье объявление интерфейса не выдает ошибку, когда компилятор, похоже, вполне может запретить неверное имя свойства во втором случае?