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

Front-end vue+express file upload and download example

Create a new server.js yarn init -y yarn add expr...

setup+ref+reactive implements vue3 responsiveness

Setup is used to write combined APIs. The interna...

Analysis of MySQL data backup and recovery implementation methods

This article uses examples to describe how to bac...

Detailed deployment of Alibaba Cloud Server (graphic tutorial)

I have recently learned web development front-end...

Detailed explanation of routes configuration of Vue-Router

Table of contents introduce Object attributes in ...

An article teaches you how to use Vue's watch listener

Table of contents Listener watch Format Set up th...

JavaScript design pattern learning proxy pattern

Table of contents Overview Implementation Protect...

Implementation of multiple instances of tomcat on a single machine

1. Introduction First of all, we need to answer a...

MySQL 8.0.18 Installation Configuration Optimization Tutorial

Mysql installation, configuration, and optimizati...

CSS inheritance method

Given a div with the following background image: ...

MySQL uses inet_aton and inet_ntoa to process IP address data

This article will introduce how to save IP addres...