#typescript
#typescript
Вопрос:
Давайте начнем с извинений за слишком общий вопрос, но я ломаю голову, как сузить его из-за непонимания того, что здесь происходит, поэтому буду корректировать на основе комментариев / ответов.
Я создал пример программы на TypeScript Playground, которая не должна компилироваться, но компилируется (используя последнюю версию TypeScript, v4.5.2 на момент написания этой статьи.) Я пытаюсь понять, почему это компилируется, чтобы понять, какие другие плохие программы могут проскользнуть мимо проверки типов и остаться незамеченными. Вот другая версия программы, которая показывает проблему во время выполнения. Есть ли какие-либо варианты, которые я пропустил, или что-нибудь, что я могу сделать, чтобы эта программа не проверяла тип?
Для удобства я также встроил рассматриваемую программу здесь:
type Settings = { 'a': boolean; 'b': string }
function setSetting<K extends keyof Settings>(p: K, v: Settings[K]): void {}
// setSetting('a', 100) // good; it fails
setSetting('a', true); // good; compiles
function breakSetSetting(k: keyof Settings, v: boolean): void {
setSetting(k, v);
}
breakSetSetting('b', true); // bad; it compiles!
Обновление: Согласно комментарию @crashmstr, использование generics for breakSettings
приводит к тому, что программа не компилируется, однако мне до сих пор неясно, почему ей было разрешено компилироваться раньше.
Комментарии:
1. Если вы используете ту же подпись generics в breakSetSetting , то вы получаете ошибку компилятора, которую вы не можете просто передать в логическом
v
значении. Как бы то ни было, максимум, что знает компилятор, это то, что вызовsetSetting
there является astring | bool
для второго параметра, иv
для этого он «работает».2. @crashmstr ага . Вероятно, вам следует написать это в качестве ответа.
3. Спасибо, я обновил вопрос, однако я все еще не уверен, почему предыдущей программе вообще удалось скомпилироваться
Ответ №1:
Когда вы определяете K
, вы определяете, что это будет 'a' | 'b'
(что есть keyof K
). Это означает, что v
это будет Settings['a' | 'b']
то, что оценивается boolean | string
как . Теперь, когда вы breakSetSetting
передаете a boolean
в setSetting
, boolean
находится в области действия boolean | string
, заставляя компилятор пройти.
Комментарии:
1. Я думаю, что я добираюсь туда, однако я не понимаю, почему это все еще разрешено компилировать. Итак, чтобы резюмировать, мое понимание проблемы заключается в том, что when
K
is выбрано как объединение,Settings[K]
также является объединением, и поскольку объединения не упорядочены, фактические значения в этих объединениях могут не совпадать. Редактировать: теперь я вижу, как компилируется первая программа. Интересно, вторая версия программы, которую я связал (которая показывает проблему во время выполнения), просто реализована с использованием проблем{...s, [p]: v}
. Может быть, есть более безопасный способ сделать эту часть?