#typescript #typescript2.0
#typescript #typescript2.0
Вопрос:
При взгляде на то, что нового в TypeScript 2.0, я нашел never
тип. Согласно документам, похоже, что это умный способ задать тип функций, которые никогда не возвращаются.
Теперь, если я все правильно прочитал, то never
может быть присвоен каждому типу, но только never
может быть присвоен never
. Итак, при написании небольшого теста в VS Code я получил следующее:
function generateError(){
throw new Error("oops");
}
function do(option: "opt1" | "opt2"){
if(option === "opt1") return true;
if(option === "opt2 ) return false;
generateError();
}
let res = do("blah");
Ну, какой ожидаемый тип res
? Согласно компилятору, это string | undefined
(что имеет смысл, хотя, должен сказать, я ожидал string
). Думаю, я не вижу смысла в создании нового типа только для представления функций, которые никогда не возвращаются. Действительно ли нам нужна эта концепция? Это просто особенность компилятора, которая помогает ему проводить лучший анализ потока?
Комментарии:
1. Предполагаемый возвращаемый тип скорее должен быть
boolean
2. Я также рассмотрел это здесь : basarat.gitbooks.io/typescript/content/docs/types/never.html
3. @basarat эта ссылка больше никуда не ведет.
4. Обновлено : basarat.gitbook.io/typescript/type-system/never
Ответ №1:
Never — это информация о том, что эта конкретная часть не должна быть доступна. Например, в этом коде
function do(): never {
while (true) {}
}
у вас бесконечный цикл, и мы не хотим повторять бесконечный цикл. Просто так.
Но реальный вопрос в том, как это может быть полезно для нас? Может быть полезно, например, при создании более продвинутых типов указывать, чем они не являются
например, давайте объявим наш собственный ненулевой тип:
type NonNullable<T> = T extends null | undefined ? never : T;
Здесь мы проверяем, имеет ли значение T значение null или не определено. Если это так, то мы указываем, что этого никогда не должно произойти. Затем при использовании этого типа:
let value: NonNullable<string>;
value = "Test";
value = null; // error
Ответ №2:
Вы можете использовать never
, чтобы гарантировать, что вы не пропустите контракт функции.
function forever(): never {
while (true) {
break; // Error because you can't leave the function.
}
}
enum Values {
A,
B
}
function choose(value: Values) {
switch (value) {
case Values.A: return "A";
}
let x: never = value; // Error because B is not a case in switch.
}
Ответ №3:
Функции, которые никогда (ever) не возвращаются, и функции, которые могут выдавать, — это не совсем одно и то же.
Например:
function foo(option: "opt1" | "opt2"): string | undefined {
if (option === "opt1") return true;
if (option === "opt2") return false;
throw new Error("unknown option");
}
function bar(option: "opt1" | "opt2"): never {
while (true) {
doOption(option);
}
}
Первый может (или не может) возвращать, но это возможно, поэтому возвращаемый тип не может быть never
. Если он может возвращать значение, возвращаемый тип, очевидно, таковым не является never
.
Второй никогда не вернется. Не значение, не неопределенный, ничего. Не существует случая, в котором оно будет возвращаться, поэтому тип может быть never
.
Существуют некоторые функции, которые выглядят как # 2, но на самом деле подпадают под # 1, обычно, когда throw
задействована или если вы используете process.exit
в node (которые не могут вернуться, поскольку они завершают процесс).
Комментарии:
1. Привет, ssube. Итак, если есть шанс возврата, он не может иметь тип never . Имеет смысл. Но тогда в чем смысл never? Мне трудно понять, почему это было введено в TypeScript…
2. Цель состоит в том, чтобы явно указать методы, которые не будут возвращать, как в
process.exit
примере. Теперь, когда компилятор знает наверняка, размещение кода после них может выдать предупреждение, точно так же, как размещение кода послеreturn
.3. Ах, так это дело компилятора? Тем не менее, не уверен, почему он там есть, потому что я почти уверен, что приведенные примеры, оправдывающие его существование, могут быть правильно выведены компилятором без этого типа … опять же, я могу ошибаться…
4. Как бы еще вы описали возвращаемый тип
process.exit
?5. хорошо, может быть, в таком случае … тем не менее, не уверен, где я буду использовать его в своих программах. Вероятно, через пару месяцев я передумаю…