Это происходит потому, что функция foo()
может принимать только iterables
. См. Приведенный ниже пример:
function foo( [a, b, c] ) {
console.log(a, b, c)
}
foo( [4, 5, 6] ); // works okay
foo( 3,4,5 ); // undefined is not a function
IMHO, spread operator
используется в качестве сборщика в этих типах таких как:
function foo( ...[a, b, c] ) {
console.log(a, b, c)
}
foo( ...[4, 5, 'v'] ); //works fine
foo(1,3,4); // also works fine
Почему foo () генерирует исключение?
Это из-за несовместимых параметров (b / w caller & amp; calee), который не имеет ничего общего с тем фактом, что в JavaScript
1[0]
естьundefined
.
instanceof
- это проверка, является ли объект экземпляром Bar
. Хотя это означает, что тип параметра также Bar
, обратное не всегда верно. Typescript использует структурную типизацию, поэтому любой объект со структурой Bar
будет совместим с параметром функции. Так что этот код совершенно корректен:
class Bar {
bar: number;
}
function doSomething(p: Bar) { }
doSomething({
bar: 10
})
Когда у вас есть личные свойства, вы не можете так легко «подделать» объект, но даже тогда мы всегда можем утверждать any
: [118 ]
class Bar {
private bar: number;
}
function doSomething(p: Bar) { }
doSomething({ // error now
bar: 10
})
doSomething({ // breaking out of type safety
bar: 10
} as any)
И если ваша кодовая база не полностью TS, то любой тип безопасности выходит за пределы окна, JS может вызывать вашу функцию TS с любым, что пожелает.
Значит ли это, что вы всегда должны включать чек? Я бы поспорил против этого. JS довольно свободен в своих типах (как и TS), и именно этого ожидают ваши пользователи. Если это крякает как утка, то это утка, старая мантра JS уходит. Если объект имеет свойства для работы с вашей функцией, он должен работать с вашей функцией независимо от того, как он был создан.
В TypeScript все работает иначе, чем в JavaScript, если вы передадите аргумент любого другого типа, отличного от того, который указан в сигнатуре функции, вы получите ошибку во время компиляции, и, следовательно, вы обязаны точно следовать типу аргументов функции.
Это зависит от вашей функции. Если это частная функция, доступ к ней имеют только вы, тогда TS может помочь убедиться, что она компилируется, это всегда правильный тип. Если это общедоступная функция, которая должна использоваться другим пользователем / стороной, то необходима проверка, если вы хотите иметь некоторую устойчивость.
Тип TS - это проектирование вашего программного обеспечения, независимо от того, насколько хорошо вы его разрабатываете, если пользователь решает неправильно его удерживать, оно ломается. Так что выставляйте только несколько общественных мест и ставьте там чеки.
Чтобы ответить на ваш обновленный вопрос:
Если возможно, что во время выполнения указан неправильный тип, каков механизм, с помощью которого это может произойти? Например, ошибка в приведении типов?
blockquote>Есть несколько причин, по которым это может произойти:
doSomething
был вызван из файла JavaScript (безcheckJs
или@ts-check
)- Поставляется объект, аналогичный
Bar
. Это то же самое структурно, но это не случайBar
.- Аргумент неверного типа был приведен к
Bar
другим разработчиком- Аргумент неверного типа был автоматически приведен к
[1115 ] Аргумент неверного типа был утвержден какany
(отсутствующие определения типа, потерянный вывод типа)Bar
плохо написанным защитником типа- Аргумент неверного типа был обработан как
[ 1117] Ваш код был отправлен и использован в среде, где нет конвейера сборки, и поэтому не может существовать ошибок во время компиляции (например, распространяться в виде пакета UMD)Bar
, потому что его определение было дополнено где-то еще в вашем проекте- Объект или массив были индексированы с использованием не -существующий ключ (TypeScript предполагает, что он никогда не может быть
undefined
)- В миксе используется сомнительно типизированная часть стандартной библиотеки (например,
Promise.resolve.call(1)
будет выдавать во время выполнения, даже если TypeScript примет это)