У меня нет небезызвестного и безопасного типа решения для вас. Ваш AttributeTrait
- это то, что я называю коррелированным типом записи . Это дискриминационное объединение, где некоторый фрагмент кода безопасен для каждого члена объединения, но компилятор не может видеть, что это безопасно для объединения в целом, потому что он теряет связь корреляции между category
и trait
свойств.
Если вы напишите избыточный код, ошибка исчезнет:
function incrementRedundant(action: AttributeTrait) {
switch (action.category) {
case "physical":
attributes[action.category].traits[action.trait]++;
return;
case "social":
attributes[action.category].traits[action.trait]++;
return;
case "mental":
attributes[action.category].traits[action.trait]++;
return;
}
}
Но, как ни старайтесь, вы не можете свернуть эти случаи в одну строку кода и получить компилятор для проверки безопасности для вас. Вот почему я подал microsoft / TypeScript # 30581 , и одна из причин, по которой я подал microsoft / TypeScript # 25051 . Поскольку вы не можете попросить компилятор обрабатывать одну строку , как если бы она была записана в операторе switch
/ case
, лучшее, что я могу придумать, это использовать введите assertion , чтобы сообщить компилятору, что вы знаете лучше, чем он.
Один из способов сделать это - немного l ie и сообщить компилятору, что attributes
на самом деле имеет все trait
с на всех category
объектах:
function increment(action: AttributeTrait) {
(attributes as
Record<AttributeTrait["category"], {
traits: Record<AttributeTrait["trait"], number>
}>
)[action.category].traits[action.trait]++;
}
Это менее безопасный тип, чем избыточный код, но, по крайней мере, он позволяет вам двигаться вперед.
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код