Detailed explanation of as, question mark and exclamation mark in Typescript

Detailed explanation of as, question mark and exclamation mark in Typescript

1. The as keyword indicates an assertion

In Typescript, there are two ways to express assertions. One is the expansion notation:

let someValue: any = "this is a string";
let strLength: number = (someValue).length;

Another way is to use the as keyword:

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

2. Question mark (?) is used for attribute definition

Question marks indicate optional properties and are generally used in property definitions, such as when used in interfaces:

interface SquareConfig {
    color?: string;
    width?: number;
}
function createSquare(config: SquareConfig) {
    if (config.color) {
        console.log(config);
    }
}

The meaning of an optional attribute is: when using this attribute, either the attribute name does not exist or it must conform to the attribute type definition.

For example, the createSquare function above will report an error when compiled:

error TS2551: Property 'clor' does not exist on type 'SquareConfig'.

What happens if you modify createSquare and change the value of config.color to undefined?

interface SquareConfig {
    color?: string;
    width?: number;
}
function createSquare(config: SquareConfig) {
    config.color = undefined;
    if (config.color) {
        console.log(config);
    }
}

There is no compilation error at this time! config.color is clearly defined as a string type?

Even if you add –strictNullChecks to compile, no error will be reported. It can be seen that the type defined by the optional attribute is not strictly treated by TypeScript, and undefined is not checked by default. It should be noted that when the above undefined is changed to null, normal compilation will not report an error, but –strictNullChecks compilation will report the following error:

error TS2322: Type 'null' is not assignable to type 'string | undefined'

From this error, we can draw the following conclusion: an optional attribute is equivalent to a union type, which unions undefined; when compiling without –strictNullChecks, null can be assigned to the undefined type. That is, the definition of SquareConfig is equivalent to the following code:

interface SquareConfig {
    color: string|undefined;
    width: number|undefined;
}

Let's compare optional attributes to normal attributes. Modify createSquare again and change the color attribute to a normal attribute.

interface SquareConfig {
    color: string;
    width?: number;
}
function createSquare(config: SquareConfig) {
    config.color = undefined;
    if (config.color) {
        console.log(config);
    }
}

Compiling with –strictNullChecks gives an error:

error TS2322: Type 'undefined' is not assignable to type 'string'

This comparison also verifies the above conclusion.

Question mark (?) is used for attribute reading

The question mark is used for attribute reading, mainly in two scenarios: one is to read array elements (such as node[i] below), and the other is to read uncertain types such as any, union, optional types (such as node[i].data), etc. As shown in the following example, save it as index.ts:

interface VNodeData {
    class?: string;
}
interface VNode {
    sel?: string;
    data?: VNodeData;
}
function test(node: VNode[]) {
    let i = 0;
    var b = node[i].data.class;
    if(b !== undefined) {
        console.log(1);
    }
}

Use tsc --strictNullChecks index.ts, error:

error TS2532: Object is possibly 'undefined'

The following will show the effects of modifying this line of code var b = node[i].data.class; one by one.

1. Modify to var b = node[i]?.data.class; and then compile. Error:

Object is possibly 'undefined'

2. Modify to var b = node[i]?.data?.class;, and then compile. The compilation is successful, and the corresponding code after compilation is:

function test(node) {
    var _a, _b;
    var i = 0;
    var b = (_b = (_a = node[i]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b["class"];
    // var b = node[i].data.class; // error if (b !== undefined) {
        console.log(1);
    }
}

var b = node[i]? means that if the value of node[i] is null or undefined, then b is equal to undefined, otherwise b=node[i].

3. Modify to var b = (node[i] as VNode).data?.class;, and then compile. The compilation is successful, and the corresponding code after compilation is:

function test(node) {
    var _a;
    var i = 0;
    var b = (_a = node[i].data) === null || _a === void 0 ? void 0 : _a["class"];
    // var b = node[i]?.data?.class;
    // var b = node[i].data.class; // error if (b !== undefined) {
        console.log(1);
    }
}

At this time, when using node[i], the Typescript compiler will no longer judge whether it is null or undefined. That is, var b = node[i] as VNode will be directly compiled into var b = node[i].

4. Modify to var b = node[i]!.data?.class, and then compile. The compilation is successful, and the corresponding code after compilation is:

function test(node) {
    var _a;
    var i = 0;
    var b = (_a = node[i].data) === null || _a === void 0 ? void 0 : _a["class"];
    // var b = (node[i] as VNode).data?.class
    // var b = node[i]?.data?.class;
    // var b = node[i].data.class; // error if (b !== undefined) {
        console.log(1);
    }
}

It can be seen that the compiled codes of 3 and 4 are exactly the same, and the role of ! is equivalent to as at this time. However, ! is only used to judge null and undefined; as can be used to change (narrow or enlarge) the type detection range. The two are equivalent only when the type followed by as is a non-empty type. As in the following example, the usage of as cannot be changed to !.

interface Cat {
    action: string;
}
interface Dog {
    action: string;
}
type Animal = Cat | Dog;
let action:Animal = {} as Cat;

in conclusion

1. as and ! are used to read attributes, both can narrow the scope of type checking, and are equivalent when used for null detection. It’s just that ! is specifically used to tell the compiler that this value cannot be a null value (null and undefined), while as is not limited to this.

2. ? can be used to define and read properties. When reading, it tells the compiler that this value may be null (null and undefined) and needs to be judged.

This is the end of this article about the detailed explanation of as, question mark and exclamation mark in Typescript. For more relevant content about as, question mark and exclamation mark in Typescript, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • React+TypeScript project construction case explanation
  • TypeScript function definition and use case tutorial
  • Learn about TypeScript data types in one article
  • Teach you how to use webpack to package and compile TypeScript code
  • In-depth understanding of the use of the infer keyword in typescript
  • Why TypeScript's Enum is problematic
  • A tutorial on how to install, use, and automatically compile TypeScript
  • TypeScript interface definition case tutorial

<<:  Detailed tutorial on configuring local yum source in CentOS8

>>:  MySQL 8.0.16 winx64 installation and configuration method graphic tutorial

Recommend

Solve the docker.socket permission problem of vscode docker plugin

Solution: Kill all .vscode related processes in t...

Specific use of Linux dirname command

01. Command Overview dirname - strip non-director...

Implementation of MySQL custom list sorting by specified field

Problem Description As we all know, the SQL to so...

MySQL database Shell import_table data import

Table of contents MySQL Shell import_table data i...

Briefly describe mysql monitoring group replication

Original text: https://dev.mysql.com/doc/refman/8...

Summary of using the reduce() method in JS

Table of contents 1. Grammar 2. Examples 3. Other...

How to use JavaScript strategy pattern to validate forms

Table of contents Overview Form validation withou...

Solution to the problem of mysql master-slave switch canal

After configuring VIP, the error message that app...

How to use Vue-router routing

Table of contents 1. Description 2. Installation ...

js implementation of verification code case

This article example shares the specific code of ...

How to build php7 with docker custom image

First, perform a simple Docker installation. To c...

Sample code for implementing DIV suspension with pure CSS (fixed position)

The DIV floating effect (fixed position) is imple...

Detailed explanation of CSS background and border tag examples

1. CSS background tag 1. Set the background color...