This is the 8th day of my participation in Gwen Challenge.
This is the third article in a series on how to implement type checking. The first two articles covered the implementation of basic types, generics, advanced types, and Override, respectively:
Based on Babel handwriting TS Type Checker
How does override implement typescript type checking
In this section, we come to the realization principle of the type guard, because the content is more, divided into two parts, the first part about the realization of ideas, the second part is code implementation.
What is a type guard
Javascript types represent possibilities, how much memory might be used, what methods might be called, and so on. Typescript types contain javascript types, and pairs of types can be intersections, unions, and inferences to produce exact types. Typescript type derivations are also possible derivations that more accurately describe specific variable types.
Precision means narrowing down the possibility of doing some type, and the goal of all type programming is to produce smaller and more accurate types, as does type guarding.
Type inference makes the whole type smaller and more accurate, while type guard makes the type temporarily smaller and more accurate when it enters a branch, making type checking more accurate.
The following code, for example, integral type is string | number, this is a combined type, when entering the if a branch type obviously can only be string, the other is not to, then can do further narrow type, this is called type guards.
function func(a: string| number) :string {
if (typeof a === 'string') {
return a.toLocaleLowerCase();
} else {
return a.toFixed(1); }}Copy the code
The purpose of type guarding is to make the overall type temporarily smaller and more accurate under certain conditions. Such conditions include typeof, instanceOf, in, ===,! ==, ==! =.
Why is it possible to shrink the type under these conditions? With access to these branches, it is obvious that a variable can only be of a different type, so the type possibilities can naturally be narrowed down further.
For example, the type guard triggered by the in operator:
=== Determine the type of guard triggered:
The same is true for instanceof, etc., as long as you enter a branch that can determine the specific type, then the type can be reduced.
In TS 4.3, type narrowing for generics is also supported (previously, type narrowing was only possible through type assertions).
Type reduction is automatic type assertion, and manual type assertion is used when type reduction or type derivation fails.
Analysis of implementation ideas
We know that type narrowing is a temporary narrowing of the type used in type checking when entering the conditional branch, so the implementation of the natural if, switch branch checking, do some processing on the type.
Ts type check is to determine all files to be checked by analyzing includes, Exclues and files of configuration files and combining the configuration of lib, types and typeRoots, and then perform recursive type check for each file successively.
When checking if or switch, we only need to check whether the test part is a BinaryExpression and operator is in, ===,! ==, instanceOf, etc.
Make different judgments according to the different operators:
- In: Determines whether left is an attribute of the type of the right variable, and if so, Narrows the type
- Instanceof: Checks whether the left type is a subtype of the right variable’s type, and if so, Narrows the type
- = = = /! ==: includes typeof and does not include Typeof:
- No Typeof: Determines whether left and right are equal, and if so, shrinks the type to a specific literal type.
- Include typeof: If one of the two sides is typeof UnaryExpression, the type is then compared, if so, the type is reduced to the specific type
conclusion
The purpose of TypScript’s advanced type derivation is to narrow down the possibilities and make typing more precise. Sometimes, when entering branches, the type is defined, and you can temporarily narrow down the type, this is called type guarding.
Trigger conditions include in, instanceof, typeof, ===,! == and so on can make the type more accurate.
Type guarding is equivalent to automatic type assertion. When the type guard can’t get it right, the type assertion AS is used to shrink the type.
When the conditional statement IfStatement or SwitchStatement is encountered, the test part is judged. If it contains in, instanceof, typeof, etc., the corresponding type is processed, and then the type check is performed.
This article hopes to help you clarify the understanding of type guard, and have the idea of implementation, the next article we will do specific code implementation.