Это является следствием улучшения безопасности типов для индексированных типов доступа , введенных в TypeScript 3.5, как реализовано в microsoft / TypeScript # 30769 . В общем случае небезопасно разрешать a[p] = b[q]
, где a
и b
относятся к одному и тому же типу объекта, а * p
и q
относятся к одному и тому же типу объединения, поскольку, если p
и q
повернуты чтобы быть различными элементами объединения, вы могли бы писать несовместимое значение. В вашем случае вы делаете a[p] = b[p]
, но с точки зрения системы типов это то же самое; все, что он видит, это то, что вы пишете и читаете свойство объекта, ключ которого имеет тип объединения "x" | "y"
, что в целом небезопасно. Он не обращает внимания на тот факт, что если вы используете одно и то же значение p
в обоих местах, то оно должно быть безопасным.
Так что начиная с TypeScript 3.5 это стало проблемой. Существует запрос на исправление, когда вы читаете или пишете «одно и то же» свойство; см. microsoft / TypeScript # 32693 . И, к счастью, согласно этого комментария похоже, что это будет исправлено для случая, когда вы буквально используете тот же идентификатор (например, p
), что и ключ. Не уверен, когда это произойдет, хотя ... проблема, похоже, в бэклоге и не запланирована для конкретного выпуска TypeScript. Так что это может занять некоторое время.
До этого времени должна быть возможность выполнить рефакторинг для универсальной c функции, поскольку в одном месте они по-прежнему допускают более ранний небезопасный доступ до TS-3.5, когда вы используют тип generi c. Это упомянуто в комментарии к # 30769 :
Одно правило, которое мы всегда имели, состоит в том, что любой данный тип (и, соответственно, любой T[K]
для идентичных *) 1031 * и K
) по определению присваивается самому себе, и это основа c несостоятельности, которую мы допускаем
Так что, если мы введем эту косвенность:
function copyProp<T, K extends keyof T>(dst: T, src: T, key: K) {
dst[key] = src[key];
}
То компилируется просто отлично, и теперь мы можем использовать его:
for (const p of ['x', 'y'] as const) {
copyProp(a, b, p);
}
, который также компилируется без ошибок. Это раздражает, но по крайней мере есть решение / обходной путь, который работает на данный момент, по крайней мере, пока не выпущено исправление для # 32693.
Последняя мысль о желании, что это можно исправить в целом, так что вы мог бы избежать переключения операторов. Некоторое время go я открывал запрос функции microsoft / TypeScript # 25051 , чтобы разрешить «анализ потока распределенного управления», где вы могли бы сказать что-то вроде type switch (p) {...}
, и чтобы компилятор оценил вложенное кодируйте блок один раз для каждого элемента типа объединения p
, и если каждый проход успешен, тогда все будет успешно. Компилятор, по-видимому, не может выполнить такой многопроходный анализ для каждого выражения с типом union, с которым он сталкивается, но я надеялся, что у нас может быть хотя бы какой-то синтаксис для его запроса в определенных c случаях. Увы, это не так (и было закрыто как дубликат одного из нескольких вопросов, которые он решит), но когда я вижу эту проблему, я начинаю задумываться и думаю о том, что могло быть ..., Вздох ...
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код