Безусловно, вам проще всего использовать утверждение типа . Это вы говорите компилятору не беспокоиться о проверке безопасности типов и что вы сами проверили его и утверждаете , что это безопасно:
for (let key in this) {
if (typeof this[key] == "string") {
this[key] = "test" as any; // assertion
this[key] = "test" as any as this[typeof key]; // or this one
}
}
Обратите внимание, что такое утверждение представляет переход ответственности за проверку безопасности типов от компилятора к вам. Вы можете легко l ie обратиться к компилятору с утверждением типа, а затем столкнуться с проблемами во время выполнения без какого-либо предупреждения от доверчивого компилятора:
this[key] = 123 as any as this[typeof key]; // ? evil liar
Так что будьте осторожны.
Попытка заставить компилятор проверить безопасность типов здесь без какого-либо утверждения - трудная задача, и, вероятно, она того не стоит. Если вам интересно, я мог бы go подробно рассмотреть это, но эскиз:
this
тип похож на Параметр типа generi c, и, следовательно, он не сужается при анализе потока управления (см. microsoft / TypeScript # 13995 ), как это делает тип, не являющийся родом c.
A for..in
l oop или Object.keys()
не сужает ключи до известных ключей итерированного объекта, поскольку объекты могут иметь больше свойств, чем знает компилятор (см. этот комментарий ).
Если вы не знаете точного литерального ключа для key
, индексированный набор свойств, такой как this[key] = ...
, в конечном итоге трактует тип свойства как пересечение из все возможные типы свойств (см. microsoft / TypeScript # 30769 ). Это безопаснее, но мешает многим обычным кодам, таким как this[key] = this[key]
.
Все это работает против вас, и самое простое, что можно сделать, это просто утверждать и двигаться дальше. Вы можете попытаться преобразовать свой код в вещи, которые компилятор считает безопасными, но это, возможно, более запутанно, чем просто утверждение типа.
Когда вы говорите, что не хотите выполнять каждое свойство одно за другим , вы можете попробовать опцию «посреди дороги», где вы упоминаете имена свойств дважды, но делаете установку только один раз:
// enumerate keys whose properties can be strings and set them
(["a", "d"] as const).forEach(k => this[k] = "test");
Если это компилируется без ошибок, это потому, что компилятор знает, что a
и d
свойства вашего класса являются строками. Он не идеален, но он является более безопасным шрифтом.
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код