Basic Types
# Basic Types
TypeScript supports nearly the same data types as JavaScript, and additionally provides the useful enum type for our convenience.
# Boolean
The most basic data type is the simple true/false value, called boolean in JavaScript and TypeScript (as well as in other languages).
let isDone: boolean = false
# Number
As in JavaScript, all numbers in TypeScript are floating-point values. These floating-point numbers are of type number. In addition to hexadecimal and decimal literals, TypeScript also supports binary and octal literals introduced in ECMAScript 2015.
let decLiteral: number = 20
let hexLiteral: number = 0x14
let binaryLiteral: number = 0b10100
let octalLiteral: number = 0o24
2
3
4
# String
Another fundamental operation in JavaScript programs is working with textual data on the web or server side. As in other languages, we use the string type to represent textual data. Like JavaScript, you can use double quotes (") or single quotes (') to denote strings.
let name: string = 'bob'
name = 'smith'
2
You can also use template strings, which can span multiple lines and embed expressions. These strings are enclosed by backticks (`), and embedded expressions use the ${ expr } syntax.
let name: string = `Yee`
let age: number = 37
let sentence: string = `Hello, my name is ${ name }.
I'll be ${ age + 1 } years old next month.`
2
3
4
5
This is equivalent to defining sentence like this:
let sentence: string = 'Hello, my name is ' + name + '.\n\n' +
'I\'ll be ' + (age + 1) + ' years old next month.'
2
# Array
TypeScript, like JavaScript, allows you to work with arrays of values. There are two ways to define arrays. The first uses the element type followed by [] to denote an array of that element type:
let list: number[] = [1, 2, 3]
The second way uses a generic array type, Array<element type>:
let list: Array<number> = [1, 2, 3]
# Tuple
Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same. For example, you may want to represent a pair of values as a string and a number:
let x: [string, number]
x = ['hello', 10] // OK
x = [10, 'hello'] // Error
2
3
When accessing an element at a known index, the correct type is retrieved:
console.log(x[0].substr(1)) // OK
console.log(x[1].substr(1)) // Error, 'number' does not have 'substr'
2
When accessing an element outside the set of known indices, a union type is used instead:
x[3] = 'world' // OK, string can be assigned to (string | number) type
console.log(x[5].toString()) // OK, 'string' and 'number' both have toString
x[6] = true // Error, boolean is not (string | number) type
2
3
4
5
Union types are an advanced topic that we will discuss in a later section.
Note: Since TypeScript 3.1, accessing out-of-bounds elements will cause an error, and we should no longer use this feature.
# Enum
The enum type is a supplement to JavaScript's standard data types. Like languages such as C#, enum types allow you to give friendly names to a set of numeric values.
enum Color {Red, Green, Blue}
let c: Color = Color.Green
2
By default, members are numbered starting from 0. You can also manually set the value of a member. For example, we change the above example to start numbering from 1:
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green
2
Or, manually assign all values:
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green
2
A handy feature of enums is that you can look up the name from a numeric value. For example, if we know the value is 2 but aren't sure which name it maps to in the Color enum, we can look up the corresponding name:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2]
console.log(colorName) // Displays 'Green' since its value is 2 in the code above
2
3
4
# any
Sometimes we want to specify a type for variables whose type isn't clear at the programming stage. These values may come from dynamic content, such as user input or third-party libraries. In these cases, we don't want the type checker to check these values and instead just let them pass through the compile-time check. We can use the any type to label these variables:
let notSure: any = 4
notSure = 'maybe a string instead'
notSure = false // could also be a boolean
2
3
The any type is very useful when rewriting existing code, as it allows you to optionally include or exclude type checking during compilation. It's also useful when you only know some of the data types. For example, you might have an array containing different types of data:
let list: any[] = [1, true, 'free']
list[1] = 100
2
3
# void
In some sense, the void type is the opposite of any -- it represents the absence of any type. You will commonly see it as the return type of functions that do not return a value:
function warnUser(): void {
console.log('This is my warning message')
}
2
3
4
Declaring a void variable isn't very useful because you can only assign undefined and null to it:
let unusable: void = undefined
# null and undefined
In TypeScript, undefined and null each have their own types called undefined and null respectively. Similar to void, their types by themselves aren't very useful:
let u: undefined = undefined
let n: null = null
2
By default, null and undefined are subtypes of all other types. This means you can assign null and undefined to variables of type number.
However, when using the --strictNullChecks flag, null and undefined are only assignable to void and their respective types, which helps avoid many common issues. If you want to pass a string or null or undefined somewhere, you can use the union type string | null | undefined. Again, we will cover union types later.
# never
The never type represents the type of values that never occur. For example, never is the return type for function expressions or arrow function expressions that always throw an exception or never return at all; variables can also be of type never when constrained by type guards that are never true.
The never type is a subtype of every type and is assignable to every type; however, no type is a subtype of never or assignable to never (except never itself). Even any is not assignable to never.
Here are some functions that return never:
// A function returning never must have an unreachable endpoint
function error(message: string): never {
throw new Error(message)
}
// Inferred return type is never
function fail() {
return error("Something failed")
}
// A function returning never must have an unreachable endpoint
function infiniteLoop(): never {
while (true) {
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# object
object represents non-primitive types, i.e., anything that is not number, string, boolean, symbol, null, or undefined.
Using the object type allows for better representation of APIs like Object.create. For example:
declare function create(o: object | null): void
create({ prop: 0 }) // OK
create(null) // OK
create(42) // Error
create('string') // Error
create(false) // Error
create(undefined) // Error
2
3
4
5
6
7
8
9
# Type Assertions
Sometimes you'll end up in a situation where you know more about a value than TypeScript does. Usually this happens when you know that the type of an entity is more specific than its current type.
Type assertions are a way to tell the compiler, "trust me, I know what I'm doing." Type assertions are like type casts in other languages but perform no special data checking or restructuring. They have no runtime impact and are used purely by the compiler. TypeScript assumes that you, the programmer, have performed whatever checks are necessary.
Type assertions have two forms. One is the "angle-bracket" syntax:
let someValue: any = 'this is a string'
let strLength: number = (<string>someValue).length
2
3
The other is the as syntax:
let someValue: any = 'this is a string'
let strLength: number = (someValue as string).length
2
3
The two forms are equivalent. Which one you use is mostly a matter of personal preference; however, when using TypeScript with JSX, only as-style assertions are allowed.