Что ключевое слово ʻis` делает в машинописном тексте?


114

Я наткнулся на код, который выглядит так:

export function foo(arg: string): arg is MyType {
    return ...
}

Мне не удалось выполнить поиск isни в документации, ни в Google, это довольно распространенное слово, которое встречается практически на каждой странице.

Что ключевое слово делает в этом контексте?

Ответы:


126
function isString(test: any): test is string{
    return typeof test === "string";
}

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length); // string function
    }
}
example("hello world");

Использование предиката типа «test is string» в указанном выше формате (вместо того, чтобы просто использовать логическое значение для возвращаемого типа, после вызова isString (), если функция возвращает true, TypeScript сузит тип до строки в любом блоке, защищенном вызов функции. Компилятор будет думать, что foo является строкой в ​​блоке, защищенном снизу (и ТОЛЬКО в блоке, защищенном ниже)

{
    console.log("it is a string" + foo);
    console.log(foo.length); // string function
}

Предикат типа используется только во время компиляции. В результате файл .js (время выполнения) не будет иметь никакого значения, потому что он не учитывает ТИП.

Я проиллюстрирую различия на следующих четырех примерах.

Например, 1: в приведенном выше примере кода не будет ошибок компиляции и ошибок времени выполнения.

Например, 2: в приведенном ниже примере кода будет ошибка компиляции (а также ошибка времени выполнения), потому что TypeScript сузил тип до строки и проверил, что toExponential не принадлежит строковому методу.

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}

Например, 3: приведенный ниже пример кода не имеет ошибки компиляции, но будет иметь ошибку времени выполнения, потому что TypeScript будет ТОЛЬКО сужать тип до строки в блоке, охраняемом, но не после, поэтому foo.toExponential не будет создавать ошибку компиляции (TypeScript не считает, что это строковый тип). Однако во время выполнения строка не имеет метода toExponential, поэтому она будет иметь ошибку времени выполнения.

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
    }
    console.log(foo.toExponential(2));
}

Например, 4: если мы не используем «test is string» (предикат типа), TypeScript не сузит тип в охраняемом блоке, и в приведенном ниже примере кода не будет ошибки компиляции, но будет ошибка времени выполнения.

function isString(test: any): boolean{
    return typeof test === "string";
}
function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}

Вывод состоит в том, что «test is string» (предикат типа) используется во время компиляции, чтобы сообщить разработчикам, что код может иметь ошибку времени выполнения. Для javascript разработчики НЕ ЗНАЮТ ошибку во время компиляции. В этом преимущество использования TypeScript.


12

Единственное использование, которое я знаю, - это один из вашего примера: указание «предиката типа» ( arg is MyType) в определяемом пользователем Type Guard.

См. В этом справочнике Защитные ограждения, определяемые пользователем.

Вот еще одна ссылка


1
Я тоже видел это в документации, какое странное дизайнерское решение, этот случай можно полностью решить, вернув тип, booleanверно?
— benjaminz

2
@benjaminz Это может служить основанием для собственного вопроса о SO, но я могу показать вам быстрый пример того, чем они отличаются. isКлючевое слово фактически заливка ошибки типа и можно ввести поймать позже в коде. См. Этот пример для получения дополнительной информации.
— Styfle

@benjaminz Я не понимаю, как это может быть обработано логическим значением. Typescript должен знать, что функция, в которую вы передаете объект, работает как защита типа. Если он просто возвращает тип true или false, как Typescript может знать, что это действительно защита типа, а не просто какая-то произвольная функция, которая возвращает true, если объект правдивый. Как он узнает, что нужно сузить тип объекта? Во-вторых, как узнать, до какого типа нужно сузить тип объекта? Что делать, если параметр относится к одному из трех типов? Необходимо знать, что trueсоответствует конкретному типу.
— Пушкин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.