Инструменты пользователя

Инструменты сайта


typescript:types:type_assertion

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
typescript:types:type_assertion [2023/02/01 22:33]
werwolf
typescript:types:type_assertion [2023/02/01 22:35] (текущий)
werwolf
Строка 1: Строка 1:
-====== Приведение типов¶ ======+====== Приведение типов ======
  
 Получение значения,​ которое не соответствует ожидаемому типу, является обычным делом для типизированных языков. Понимание причин,​ лежащих в основе несоответствий,​ а также всевозможные способы их разрешений,​ являются целями данной главы. Получение значения,​ которое не соответствует ожидаемому типу, является обычным делом для типизированных языков. Понимание причин,​ лежащих в основе несоответствий,​ а также всевозможные способы их разрешений,​ являются целями данной главы.
  
-===== Утверждение типов - общее¶ =====+===== Приведение типов - общее =====
  
 При разработке приложений на языках со статической типизацией время от времени может возникнуть нестыковка из-за несоответствия типов. Простыми словами,​ приходится работать с объектом,​ принадлежащим к известному типу, но ограниченному более специализированным (менее конкретным) интерфейсом. При разработке приложений на языках со статической типизацией время от времени может возникнуть нестыковка из-за несоответствия типов. Простыми словами,​ приходится работать с объектом,​ принадлежащим к известному типу, но ограниченному более специализированным (менее конкретным) интерфейсом.
Строка 12: Строка 12:
  
 Возвращаясь к методу ''​querySelector()'',​ стоит уточнить,​ что результатом его вызова может стать любой элемент,​ находящийся в dom-дереве. Если бы в качестве типа возвращаемого значения был указан тип ''​HTMLElement'',​ то операция получения элемента ''<​script>''​ или ''<​link>''​ завершилась бы неудачей,​ так как они не принадлежат к этому типу. Именно поэтому методу ''​querySelector()''​ в качестве типа возвращаемого значения указан более базовый тип ''​Element''​. Возвращаясь к методу ''​querySelector()'',​ стоит уточнить,​ что результатом его вызова может стать любой элемент,​ находящийся в dom-дереве. Если бы в качестве типа возвращаемого значения был указан тип ''​HTMLElement'',​ то операция получения элемента ''<​script>''​ или ''<​link>''​ завершилась бы неудачей,​ так как они не принадлежат к этому типу. Именно поэтому методу ''​querySelector()''​ в качестве типа возвращаемого значения указан более базовый тип ''​Element''​.
-<​code>​+ 
 +<​code ​javascript>
 // <canvas id="​stage"​ data-unactive="​false"></​canvas>​ // <canvas id="​stage"​ data-unactive="​false"></​canvas>​
  
Строка 23: Строка 24:
 Попросить - дословно означает,​ что разработчик может лишь попросить вывод типов пересмотреть отношение к типу. Но решение разрешить операцию или нет все равно остается за последним. Попросить - дословно означает,​ что разработчик может лишь попросить вывод типов пересмотреть отношение к типу. Но решение разрешить операцию или нет все равно остается за последним.
  
-Выражаясь человеческим языком,​ в TypeScript процесс,​ вынуждающий вывод типов пересмотреть свое отношение к какому-либо типу называется ​утверждением типа (''​Type Assertion''​).+Выражаясь человеческим языком,​ в TypeScript процесс,​ вынуждающий вывод типов пересмотреть свое отношение к какому-либо типу называется ​Приведением типа (''​Type Assertion''​). 
 + 
 +Формально Приведение типа похоже на преобразование (приведение) типов (type conversion, typecasting) но, поскольку в скомпилированном коде от типов не остается и следа, то по факту это совершенно другой механизм. Именно поэтому он и называется Приведение. Утверждая тип, разработчик говорит компилятору — “поверь мне, я знаю, что делаю” (Trust me, I know what I'm doing).
  
-Формально утверждение типа похоже на преобразование (приведениетипов (type conversion, typecasting) но, поскольку в скомпилированном ​коде от типов не остается ​и следа, то по факту это совершенно другой механизм. Именно поэтому он и называется утверждение. Утверждая типразработчик говорит ​компилятору — “поверь мне, я знаю, что делаю” (Trust me, I know what I'm doing).+Нельзя не уточнить, чтохотя в TypeScript и существует термин Приведение типа, по ходу изложения ​в качестве синонимов будут употребляться слова преобразованиереже — приведение. А также, ​не будет лишним напомнить, что приведение ​— это процесс, в котором объект одного ​типа преобразуется в объект другого типа.
  
-Нельзя не уточнить,​ что, хотя в TypeScript и существует термин утверждение типа, по ходу изложения в качестве ​синонимов будут употребляться слова преобразование,​ реже — приведение. А также, не будет лишним напомнить,​ что приведение — это процесс, в котором объект одного типа преобразуется в объект другого типа.+===== Приведение типа синтаксис ​=====
  
-===== Утверждение типа синтаксис¶ =====+Одним из способов указать компилятору на принадлежность значения к заданному типу является механизм утверждения типа ​при помощи угловых ​скобок ''<​ConcreteType>'',​ заключающих в себе конкретный тип, ​к которому и будет выполняться преобразование. Приведение типа располагается строго перед выражением,​ результатом выполнения которого будет преобразуемый тип.
  
-Одним из способов указать компилятору на принадлежность значения к заданному типу является механизм утверждения типа при помощи угловых скобок ''<​ConcreteType>'',​ заключающих в себе конкретный тип, к которому и будет выполняться преобразование. Утверждение типа располагается строго перед выражением,​ результатом выполнения которого будет преобразуемый тип. +<​code ​javascript>
-<​code>​+
 <​ToType>​FromType;​ <​ToType>​FromType;​
 </​code>​ </​code>​
Строка 38: Строка 40:
 Перепишем предыдущий код и исправим в нем ошибку,​ связанную с несоответствием типов. Перепишем предыдущий код и исправим в нем ошибку,​ связанную с несоответствием типов.
  
-<​code>​+<​code ​javascript>
 // <canvas id="​stage"​ data-unactive="​false"></​canvas>​ // <canvas id="​stage"​ data-unactive="​false"></​canvas>​
  
Строка 49: Строка 51:
 Если тип, к которому разработчик просит преобразовать компилятор,​ не совместим с преобразуемым типом, то в процессе утверждения возникнет ошибка. Если тип, к которому разработчик просит преобразовать компилятор,​ не совместим с преобразуемым типом, то в процессе утверждения возникнет ошибка.
  
-<​code>​+<​code ​javascript>
 class Bird { class Bird {
   public fly(): void {}   public fly(): void {}
Строка 64: Строка 66:
 Кроме того, существуют ситуации,​ в которых возникает необходимость множественного последовательного преобразования. Ярким примером являются значения,​ полученные от dom элементов,​ которые воспринимаются разработчиком как числовые или логические,​ но по факту принадлежат к строковому типу. Кроме того, существуют ситуации,​ в которых возникает необходимость множественного последовательного преобразования. Ярким примером являются значения,​ полученные от dom элементов,​ которые воспринимаются разработчиком как числовые или логические,​ но по факту принадлежат к строковому типу.
  
-<​code>​+<​code ​javascript>
 // <div id="#​container"></​div>​ // <div id="#​container"></​div>​
  
Строка 75: Строка 77:
  
 Дело в том, что в TypeScript невозможно привести тип ''​string''​ к типу ''​number''​. Дело в том, что в TypeScript невозможно привести тип ''​string''​ к типу ''​number''​.
-<​code>​+ 
 +<​code ​javascript>
 // <div id="#​container"></​div>​ // <div id="#​container"></​div>​
  
Строка 91: Строка 94:
  
 Но осуществить задуманное можно преобразовав тип ''​string''​ сначала в тип ''​any'',​ а уже затем — в тип ''​number''​. Но осуществить задуманное можно преобразовав тип ''​string''​ сначала в тип ''​any'',​ а уже затем — в тип ''​number''​.
-<​code>​+ 
 +<​code ​javascript>
 // <div id="#​container"></​div>​ // <div id="#​container"></​div>​
  
Строка 109: Строка 113:
  
 Стоит также заметить,​ что данный способ утверждения типа, кроме синтаксиса,​ больше ничем не отличается от указания с помощью оператора ''​as''​. Стоит также заметить,​ что данный способ утверждения типа, кроме синтаксиса,​ больше ничем не отличается от указания с помощью оператора ''​as''​.
-===== Утверждение типа с помощью оператора ​as¶ =====+ 
 +===== Приведение типа с помощью оператора ​as =====
  
 В отличие от синтаксиса угловых скобок,​ которые указываются перед преобразуемым типом, оператор ''​as''​ указывается между преобразуемым и типом, к которому требуется преобразовать. В отличие от синтаксиса угловых скобок,​ которые указываются перед преобразуемым типом, оператор ''​as''​ указывается между преобразуемым и типом, к которому требуется преобразовать.
-<​code>​+ 
 +<​code ​javascript>
 FromType as ToType; FromType as ToType;
 </​code>​ </​code>​
Строка 119: Строка 125:
  
 Обычное дело: при помощи метода ''​querySelector()''​ получить объект,​ принадлежащий к типу ''​HTMLElement'',​ и подписать его на событие ''​click''​. Задача заключается в том, что при возникновении события нужно изменить значение поля ''​dataset'',​ объявленного в типе ''​HTMLElement''​. Было бы нерационально снова получать ссылку на объект при помощи метода ''​querySelector()'',​ ведь нужный объект хранится в свойстве объекта события ''​target''​. Но дело в том, что свойство ''​target''​ имеет тип ''​EventTarget'',​ который не находится в иерархической зависимости с типом ''​HTMLElement'',​ имеющим нужное свойство ''​dataset''​. Обычное дело: при помощи метода ''​querySelector()''​ получить объект,​ принадлежащий к типу ''​HTMLElement'',​ и подписать его на событие ''​click''​. Задача заключается в том, что при возникновении события нужно изменить значение поля ''​dataset'',​ объявленного в типе ''​HTMLElement''​. Было бы нерационально снова получать ссылку на объект при помощи метода ''​querySelector()'',​ ведь нужный объект хранится в свойстве объекта события ''​target''​. Но дело в том, что свойство ''​target''​ имеет тип ''​EventTarget'',​ который не находится в иерархической зависимости с типом ''​HTMLElement'',​ имеющим нужное свойство ''​dataset''​.
-<​code>​+ 
 +<​code ​javascript>
 // <span id="​counter"></​span>​ // <span id="​counter"></​span>​
  
Строка 133: Строка 140:
  
 Но эту проблему легко решить с помощью оператора утверждения типа ''​as''​. Кроме того, с помощью этого же оператора можно привести тип ''​string'',​ к которому принадлежат все свойства,​ находящиеся в ''​dataset'',​ к типу ''​any'',​ а уже затем к типу ''​number''​. Но эту проблему легко решить с помощью оператора утверждения типа ''​as''​. Кроме того, с помощью этого же оператора можно привести тип ''​string'',​ к которому принадлежат все свойства,​ находящиеся в ''​dataset'',​ к типу ''​any'',​ а уже затем к типу ''​number''​.
-<​code>​+ 
 +<​code ​javascript>
 let element = document.querySelector( let element = document.querySelector(
   '#​counter'​   '#​counter'​
Строка 150: Строка 158:
 В случае несовместимости типов возникнет ошибка. В случае несовместимости типов возникнет ошибка.
  
-<​code>​+<​code ​javascript>
 class Bird { class Bird {
   public fly(): void {}   public fly(): void {}
Строка 166: Строка 174:
  
 Факт, что над значением,​ принадлежащим к типу ''​any'',​ разрешено выполнение любых операций,​ означает,​ что компилятор их не проверяет. Другими словами,​ разработчик,​ указывая тип ''​any'',​ усложняет процесс разработки,​ мешая компилятору проводить статический анализ кода, а также лишает себя помощи со стороны редактора кода. Когда разработчику известно,​ к какому типу принадлежит значение,​ можно попросить компилятор изменить мнение о принадлежности значения к его типу с помощью механизма утверждения типов. Факт, что над значением,​ принадлежащим к типу ''​any'',​ разрешено выполнение любых операций,​ означает,​ что компилятор их не проверяет. Другими словами,​ разработчик,​ указывая тип ''​any'',​ усложняет процесс разработки,​ мешая компилятору проводить статический анализ кода, а также лишает себя помощи со стороны редактора кода. Когда разработчику известно,​ к какому типу принадлежит значение,​ можно попросить компилятор изменить мнение о принадлежности значения к его типу с помощью механизма утверждения типов.
-<​code>​+ 
 +<​code ​javascript>
 class DataProvider { class DataProvider {
   constructor(readonly data: any) {}   constructor(readonly data: any) {}
Строка 181: Строка 190:
 </​code>​ </​code>​
  
-Напоследок,​ стоит сказать,​ что выражения,​ требующие утверждения типа при работе с dom api — это неизбежность. Кроме того, для работы с методом ''​document.querySelector()'',​ который был использован в примерах к этой главе, вместо приведения типов с помощью операторов ''<​Type>''​ или ''​as''​ предпочтительней конкретизировать тип с помощью обобщения,​ которое рассматривается в главе [[:​typescript:​types|Обобщения (Generics)]]. Но в случае,​ если ​утверждение требуется для кода, написанного самим разработчиком,​ то скорее всего, это следствие плохо продуманной архитектуры.+Напоследок,​ стоит сказать,​ что выражения,​ требующие утверждения типа при работе с dom api — это неизбежность. Кроме того, для работы с методом ''​document.querySelector()'',​ который был использован в примерах к этой главе, вместо приведения типов с помощью операторов ''<​Type>''​ или ''​as''​ предпочтительней конкретизировать тип с помощью обобщения,​ которое рассматривается в главе [[.|Обобщения (Generics)]]. Но в случае,​ если ​Приведение требуется для кода, написанного самим разработчиком,​ то скорее всего, это следствие плохо продуманной архитектуры.
  
-===== Приведение (утверждение) к константе (const assertion)¶ =====+===== Приведение (Приведение) к константе (const assertion) =====
  
 Ни для кого не секрет,​ что с точки зрения JavaScript, а, следовательно,​ и TypeScript, все примитивные литеральные значения являются константными значениями. С точки зрения среды исполнения два эквивалентных литерала любого литерального типа являются единым значением. То есть, среда исполнения расценивает два строковых литерала '''​text'''​ и '''​text'''​ как один литерал. То же справедливо и для остальных литералов,​ к которым помимо типа ''​string''​ также относятся типы ''​number'',​ ''​boolean''​ и ''​symbol''​. Ни для кого не секрет,​ что с точки зрения JavaScript, а, следовательно,​ и TypeScript, все примитивные литеральные значения являются константными значениями. С точки зрения среды исполнения два эквивалентных литерала любого литерального типа являются единым значением. То есть, среда исполнения расценивает два строковых литерала '''​text'''​ и '''​text'''​ как один литерал. То же справедливо и для остальных литералов,​ к которым помимо типа ''​string''​ также относятся типы ''​number'',​ ''​boolean''​ и ''​symbol''​.
  
-Тем не менее сложно найти разработчика TypeScript, не испытавшего трудностей,​ создаваемых выводом типов при определении конструкций,​ которым предстоит проверка на принадлежность к литеральному типу..<​code>​+Тем не менее сложно найти разработчика TypeScript, не испытавшего трудностей,​ создаваемых выводом типов при определении конструкций,​ которым предстоит проверка на принадлежность к литеральному типу.. 
 + 
 +<​code ​javascript>
 type Status = 200 | 404; type Status = 200 | 404;
 type Request = { status: Status }; type Request = { status: Status };
Строка 196: Строка 207:
 </​code>​ </​code>​
  
-В коде выше ошибка возникает по причине того, что вывод типов определяет принадлежность значения переменной ''​status''​ к типу ''​number'',​ а не литеральному числовому типу ''​200''​.<​code>​+В коде выше ошибка возникает по причине того, что вывод типов определяет принадлежность значения переменной ''​status''​ к типу ''​number'',​ а не литеральному числовому типу ''​200''​. 
 + 
 +<​code ​javascript>
 // вывод типов видит как // вывод типов видит как
 let status: number = 200; let status: number = 200;
Строка 205: Строка 218:
  
 Прежде всего не будет лишним упомянуть,​ что данную проблему можно решить с помощью механизма утверждения при помощи таких операторов как ''​as''​ и угловых скобок ''<>''​. Прежде всего не будет лишним упомянуть,​ что данную проблему можно решить с помощью механизма утверждения при помощи таких операторов как ''​as''​ и угловых скобок ''<>''​.
-<​code>​+ 
 +<​code ​javascript>
 type Status = 200 | 404; type Status = 200 | 404;
 type Request = { status: Status }; type Request = { status: Status };
Строка 218: Строка 232:
 </​code>​ </​code>​
  
-Но лучшим решением будет специально созданный для подобных случаев механизм,​ позволяющий производить ​утверждение к константе.+Но лучшим решением будет специально созданный для подобных случаев механизм,​ позволяющий производить ​Приведение к константе.
  
-Константное ​утверждение производится с помощью оператора ''​as''​ или угловых скобок ''<>''​ и говорит компилятору,​ что значение является константным.<​code>​+Константное ​Приведение производится с помощью оператора ''​as''​ или угловых скобок ''<>''​ и говорит компилятору,​ что значение является константным. 
 + 
 +<​code ​javascript>
 type Status = 200 | 404; type Status = 200 | 404;
 type Request = { status: Status }; type Request = { status: Status };
Строка 230: Строка 246:
 </​code>​ </​code>​
  
-Утверждение, что значение является константным,​ заставляет вывод типов расценивать его как принадлежащее к литеральному типу. ​Утверждение к константе массива заставляет вывод типов определять его принадлежность к типу ''​readonly tuple''​.<​code>​+Приведение,​ что значение является константным,​ заставляет вывод типов расценивать его как принадлежащее к литеральному типу. ​Приведение к константе массива заставляет вывод типов определять его принадлежность к типу ''​readonly tuple''​. 
 + 
 +<​code ​javascript>
 let a = [200, 404]; // let a: number[] let a = [200, 404]; // let a: number[]
  
Строка 237: Строка 255:
 </​code>​ </​code>​
  
-В случае с объектным типом, ​утверждение к константе рекурсивно помечает все его поля как ''​readonly''​. Кроме того, все его поля, принадлежащие к примитивным типам, расцениваются как литеральные типы. +В случае с объектным типом, ​Приведение к константе рекурсивно помечает все его поля как ''​readonly''​. Кроме того, все его поля, принадлежащие к примитивным типам, расцениваются как литеральные типы. 
-<​code>​+ 
 +<​code ​javascript>
 type NotConstResponseType = { type NotConstResponseType = {
   status: number;   status: number;
Строка 259: Строка 278:
 </​code>​ </​code>​
  
-Но стоит помнить,​ что ​утверждение к константе применимо исключительно к литералам таких типов, как ''​number'',​ ''​string'',​ ''​boolean'',​ ''​array''​ и ''​object''​.<​code>​+Но стоит помнить,​ что ​Приведение к константе применимо исключительно к литералам таких типов, как ''​number'',​ ''​string'',​ ''​boolean'',​ ''​array''​ и ''​object''​. 
 + 
 +<​code ​javascript>
 let a = '​value'​ as const; // Ok - '​value'​ является литералом,​ let a: "​value"​ let a = '​value'​ as const; // Ok - '​value'​ является литералом,​ let a: "​value"​
 let b = 100 as const; // Ok - 100 является литералом,​ let b: 100 let b = 100 as const; // Ok - 100 является литералом,​ let b: 100
Строка 280: Строка 301:
 В случае,​ когда литералы ссылочных типов (массивы и объекты) ассоциированы со значением,​ также принадлежащим к ссылочному типу, то они представляются такими,​ какими были на момент ассоциации. Кроме того, поведение механизма приведения к константе зависит от другого механизма — деструктуризации. В случае,​ когда литералы ссылочных типов (массивы и объекты) ассоциированы со значением,​ также принадлежащим к ссылочному типу, то они представляются такими,​ какими были на момент ассоциации. Кроме того, поведение механизма приведения к константе зависит от другого механизма — деструктуризации.
  
-<​code>​+<​code ​javascript>
 let defaultObject = { f: 100 }; // let defaultObject:​ {f: number;} let defaultObject = { f: 100 }; // let defaultObject:​ {f: number;}
 let constObject = { f: 100 } as const; // let constObject:​ {readonly f: 100;} let constObject = { f: 100 } as const; // let constObject:​ {readonly f: 100;}
Строка 306: Строка 327:
 По причине,​ что объектные типы данных,​ хранящиеся в массиве,​ подчиняются описанным выше правилам,​ подробное рассмотрение процесса утверждения массива к константе будет опущено. По причине,​ что объектные типы данных,​ хранящиеся в массиве,​ подчиняются описанным выше правилам,​ подробное рассмотрение процесса утверждения массива к константе будет опущено.
  
-И последнее,​ о чем стоит упомянуть — утверждение к константе применимо только к простым выражениям.+И последнее,​ о чем стоит упомянуть — Приведение к константе применимо только к простым выражениям.
  
-<​code>​+<​code ​javascript>
 let a = (Math.round(Math.random() * 1) let a = (Math.round(Math.random() * 1)
   ? '​yes'​   ? '​yes'​
Строка 317: Строка 338:
 </​code>​ </​code>​
  
-===== Утверждение в сигнатуре (Signature Assertion)¶ =====+===== Приведение в сигнатуре (Signature Assertion) =====
  
-Помимо функций,​ реализующих механизм утверждения типа, в TypeScript существует механизм утверждения в сигнатуре,​ позволяющий определять утверждающие функции,​ вызов которых,​ в случае невыполнения условия,​ приводит к выбрасыванию исключения. Для того чтобы объявить утверждающую функцию,​ в её сигнатуре (там, где располагается возвращаемое значение) следует указать ключевое слово ''​asserts'',​ а затем параметр принимаемого на вход условия.<​code>​+Помимо функций,​ реализующих механизм утверждения типа, в TypeScript существует механизм утверждения в сигнатуре,​ позволяющий определять утверждающие функции,​ вызов которых,​ в случае невыполнения условия,​ приводит к выбрасыванию исключения. Для того чтобы объявить утверждающую функцию,​ в её сигнатуре (там, где располагается возвращаемое значение) следует указать ключевое слово ''​asserts'',​ а затем параметр принимаемого на вход условия. 
 + 
 +<​code ​javascript>
 function identifier(condition:​ any): asserts condition { function identifier(condition:​ any): asserts condition {
   if (!condition) {   if (!condition) {
Строка 331: Строка 354:
 Если принадлежность значения к указанному типу подтверждается,​ то далее по коду компилятор будет рассматривать его в роли этого типа. Иначе выбрасывается исключение. Если принадлежность значения к указанному типу подтверждается,​ то далее по коду компилятор будет рассматривать его в роли этого типа. Иначе выбрасывается исключение.
  
-<​code>​ +<​code ​javascript
-// утверждение в сигнатуре+// Приведение в сигнатуре
 function isStringAssert(condition:​ any): asserts condition { function isStringAssert(condition:​ any): asserts condition {
   if (!condition) {   if (!condition) {
Строка 339: Строка 362:
 } }
  
-// утверждение типа+// Приведение типа
 function isString(value:​ any): value is string { function isString(value:​ any): value is string {
   return typeof value === '​string';​   return typeof value === '​string';​
Строка 351: Строка 374:
   isStringAssert(isString(text));​ // механизм "​утверждения типа"​   isStringAssert(isString(text));​ // механизм "​утверждения типа"​
  
-  text.touppercase();​ // ..после ​утверждениея как тип string+  text.touppercase();​ // ..после ​Приведениея как тип string
 }; };
 </​code>​ </​code>​
Строка 357: Строка 380:
 При использовании механизма утверждения в сигнатуре с механизмом утверждения типа, условие из вызова утверждающей функции можно перенести в её тело. При использовании механизма утверждения в сигнатуре с механизмом утверждения типа, условие из вызова утверждающей функции можно перенести в её тело.
  
-<​code>​+<​code ​javascript>
 function isStringAsserts( function isStringAsserts(
   value: any   value: any
Строка 377: Строка 400:
 Стоит обратить внимание на то, что механизм утверждения типа не будет работать в случае переноса условного выражения в тело утверждающей функции,​ сигнатура которой лишена утверждения типов и содержит исключительно утверждения в сигнатуре. Стоит обратить внимание на то, что механизм утверждения типа не будет работать в случае переноса условного выражения в тело утверждающей функции,​ сигнатура которой лишена утверждения типов и содержит исключительно утверждения в сигнатуре.
  
-<​code>​+<​code ​javascript>
 function isStringAsserts( function isStringAsserts(
   value: any   value: any
Строка 391: Строка 414:
   isStringAsserts(text);​ // условие определено в утверждающей функции   isStringAsserts(text);​ // условие определено в утверждающей функции
  
-  text.touppercase();​ // нет ошибки,​ потому что ​утверждение типов не работает+  text.touppercase();​ // нет ошибки,​ потому что ​Приведение типов не работает
 }; };
 </​code>​ </​code>​
- 
- 
typescript/types/type_assertion.1675280004.txt.gz · Последние изменения: 2023/02/01 22:33 — werwolf