Разделить Assessment
на 2 типа; с scoreTotal
и без него. Вы можете сделать это наиболее элегантно с типами «tagged union».
interface AssessmentBase {
items: Question[];
time?: number; // optional property
}
interface AssessmentWithoutScoreTotal extends AssessmentBase {
type: "AssessmentWithoutScoreTotal",
}
interface AssessmentWithScoreTotal extends AssessmentBase {
type: "AssessmentWithScoreTotal",
scoreTotal: number; // runtime computed property (sum of questions scores)
}
type Assessment = AssessmentWithoutScoreTotal
& AssessmentWithScoreTotal;
Конечно, Assessment
больше не будет классом. Но вы можете сделать классом AssessmentWithoutScoreTotal
или AssessmentWithScoreTotal
, в зависимости от ваших потребностей. Но разве это должен быть класс? Я считаю, что простые интерфейсы работают намного лучше в большинстве ситуаций.
Тем не менее, вы должны быть осторожны, чтобы не изменить свойство items
после вычисления totalScore
, поэтому может иметь смысл ввести это а также:
interface Question {
readonly score: number;
statement: string;
responses: string[];
correctResponse: string;
}
interface AssessmentBase {
time?: number; // optional property
}
interface AssessmentWithoutScoreTotal extends AssessmentBase {
type: "AssessmentWithoutScoreTotal",
items: Question[];
}
interface AssessmentWithScoreTotal extends AssessmentBase {
type: "AssessmentWithScoreTotal",
scoreTotal: number; // runtime computed property (sum of questions scores)
readonly items: readonly Question[]; // Shouldn't mutate the scores anymore, since total has been precomputed.
}
type Assessment = AssessmentWithoutScoreTotal
& AssessmentWithScoreTotal;