This article is the first in a series of TypeScript Tutorials.

  1. Know the TypeScript
  2. Install the TypeScript
  3. Basic Type (1)

Starting with this article, we’ll take a look at TypeScript’s type system. As we mentioned earlier, TypeScript is a superset of JavaScript, an “enhanced version” of JavaScript. You can see this in TypeScript’s primitive types. The data type of TS is almost the same as that of JS, and some additional data types are provided for our convenience.

First, let’s look at the six primitive data types used in JavaScript in TypeScript: number, String, Boolean, NULL, undefined, and Symbol.

Primitive data type

numbertype

In TypeScript, number is used to indicate that variables are numeric types. In line with JavaScript, all values in TypeScript are floating point numbers, which can be expressed in binary, octal, decimal, and hexadecimal.

let decimalNumber: number = 42
let hexNumber: number = 0x2A
let binaryNumber: number = 0b101010
let octalNumber: number = 0o52
Copy the code

Binary and octal representations are written in ES6 using the prefix ‘0b’ (or ‘0b’) and ‘0o’ (or ‘0O’) respectively. Starting with ES5, octal prefix ‘0’ is no longer allowed. If target in ‘tsconfig’ is later than ES5, TypeScript will prompt you to disallow the use of the ‘0’ prefix for octal.

In addition to floating point numbers, JavaScript has a special set of values: Infinity, -infinity, and NaN, which are also of type number.

const positiveLargestNumber: number = Infinity
const negativeLargestNumber: number = -Infinity

const notANumber: number = NaN
Copy the code

Infinity is + Infinity, which is used to represent the value beyond the maximum that JS can represent. The value may be different in different environments, and can be viewed through number. MAX_VALUE, which is 1.7976931348623157E+308. And that corresponds to -infinity, minus Infinity.

Note the distinction between ** -infinity ** and ** infinitesimal **. Negative infinity means a negative number that is smaller than any number, and infinitesimal means a positive number that approaches zero as the limit. Infinitesimal values in JS can be viewed by ‘number.min_value’, generally ‘5e-324’.

NaN represents a case where an operand that should return a value does not. Such as:

let newNumber: number = Number('a') // => NaN
Copy the code

For more information, see: ECMAScript 6 Getting Started – Numerical extensions

stringtype

As in other programming languages, strings are an essential type for representing textual data. You can declare a variable as a string through string.

const theAnswer: number = 42
let sentence: string = `The Answer to the Ultimate Question of Life, The Universe, and Everything is ${ theAnswer }. `
Copy the code

In TypeScript you can still use double quotation marks (“) and single quotation marks (‘) to represent strings. In addition, you can use the template string syntax provided by ES6. TypeScript automatically compiles this to a string concatenation.

// Compile the result
var theAnswer = 42;
var sentence = "The Answer to the Ultimate Question of Life, The Universe, and Everything is " + theAnswer + ".";
Copy the code

booleantype

Booleans are the most basic data types, with only two possible values: true and false. Boolean is used in TypeScript to represent Boolean types.

let num: number = - 10
let isPositive: boolean = num > 0
Copy the code

symboltype

Symbol is a new data type in ES6 that represents unique values and can only be generated by the symbol function. For more information, see ECMAScript 6 Primer – Symbol.

const sym: symbol = Symbol(a)Copy the code

In fact, the underlying data type symbol is not described in detail on the TypeScript website. I think there are two reasons:

  1. symbolValues can only be passedSymbol()Function generated because ofType inference(as we’ll see later), there is no need to specifically declare the variable issymbolType.
  2. symbolThe uniqueness of is dependent on the underlying implementation and is not easy to polyfill, so it is not recommended if the build target is lower than ES6symbol.

For completeness, however, it is briefly mentioned here.

undefinednulltype

In JavaScript, both undefined and null are used to represent null values. As two primitive data types, variables of undefined type can only be assigned to undefined, and variables of null type can only be assigned to NULL.

// Generally speaking, it doesn't make much sense to define a variable of type undefined or null directly
let u: undefined = undefined
let n: null = null
Copy the code

By default, undefined and NULL are subtypes of all other types. That is, if undefined and null are assigned to any other type of variable.

Such as:

let person: string = 'Jerry'
person = null / / effective
Copy the code

However, if strictNullChecks is enabled in tsconfig, undefined and null can only be assigned to variables of type void or any and variables of their own type. This option is highly recommended, as it can help avoid many common problems.

undefinednullThe relationship between

Although undefined and null both represent null values, they are fundamentally different. Undefined means that the variable is declared but not initialized, and null logically means an empty object pointer (which is why typeof NULL === ‘object’).

In any case, it is not necessary to explicitly set the value of a variable to undefined, but the same rule does not apply to NULL. In other words, as long as the variable intended to hold an object does not actually hold the object, you should explicitly let that variable hold a null value. — Nicholas C.Zakas, JavaScript Advanced Programming

High-level types

voidtype

The void type means that there is no type, which may sound paradoxical. But let’s consider the case: if a function has no return value, how do we represent its type? This is where void comes in handy. This is very similar to C.

function warning() :void {
    console.log('WARNING! ')}Copy the code

Of course, you can also specify the return type as undefined. Because in JS, if a function returns no value, undefind is returned by default. However, using the void type makes the representation clearer.

However, declaring a void variable is not very useful because you can only assign it to null and undefined.

Note the distinction with the void operator. The void operator evaluates a given expression and returns undefined. If you’ve been on the front end for years, you’re probably familiar with javascript:void(0); Code like this. If you’re interested, check it out here.

anytype

In a way, any is like the opposite of void, and any type is a subtype of any. In other words, a variable of type any can be assigned a value of any type.

let anything: any = "Ohh, that's crazy"
anything = 42
Copy the code

There are two things to note about the any type.

First, if a variable is declared without its type and is not initialized (because type inference automatically determines the type), it is treated as any.

let something   // Equivalent to let something: any;
something = 'autochess'
something = 6
Copy the code

Second, any property can be accessed on a variable of type any, even if it doesn’t exist.

let something: any = 42
something.mayExist()    // No problem, because it may exist at runtime
something.toFixed() // No problem, although it does exist, the compiler does not check it
Copy the code

In fact, the any type is an “escape” option that TypeScript provides. For variables of type any, the compiler does no type checking and simply passes them through type checking. This is especially useful when introducing third-party libraries and rewriting old JS code to TS.

However, be careful not to abuse the any type. Misusing any makes TS useless.

nevertype

Never is used to indicate the type of value that never exists. Never is a subtype of any type, but no type is a subtype of Never.

The never type can be difficult for beginners to understand. But for TypeScript, a language that analyzes code flow, the never type is a natural necessity.

The never type is used in two cases:

  1. Term used to describe a function that never returns a value
  2. Used to describe a function that always throws an error
// The first case
function neverStop() :never {
    while (true) {
        // do something}}// The second case
function error(message: string) :never {
    throw new Error(message)
}
Copy the code

In both cases, the return type of the function is never.

The never type can also be used as a type annotation for variables (e.g., let foo: never;). But there is no point in doing so.

Here’s an example of how to use the never type:

function checkNumber(x: string | number) :boolean {
    if (typeof x === 'number') {
        return true
    } else if (typeof x === 'string') {
        return false
    }
    
    return fail('Failure')}function fail(message: string) :never {
    throw new Error(message)
}
Copy the code

For the checkNumber function above, TypeScript would have reported an error without return fail(‘Failure’) because not all conditional statements return a value. When x is neither a number nor a string, The function returns undefined by default, but undefined is not compatible with Boolean in strict mode. But because the fail function returns never as a subtype of Boolean, all of the above can be compiled. This is why never must be a subtype of any type.

This is just an example of the never type to help you understand. To really understand the never genre, you have to think about it in real life.

conclusion

This article focuses on TypeScript primitive data types and several advanced types. In this article, you can see how powerful and complete the TypeScript type system is.

That’s not all, of course. In the next article we’ll look at several other TypeScript advanced types: Object, Array, Tuple, and Enum. Stay tuned ~