Types page
Learn how to declare types in TypeScript.
Overview
In this part, we will:
- Discover how to declare the various types used in TypeScript
- Discuss how types can be inferred
- Show how to assert types
The exercises will teach you how to:
- Spot and correct basic type mistakes
- Create a typed variable
Basic Types
Types explain what you can and can’t do with a value, take for example numbers and strings. In JavaScript, on strings, you have access to .length
, on a number you do not. Types also determine what will happen when you apply operators to values. For example, the +
operator, what does the following do?
console.log(a + b);
Some might say it adds a
and b
together, others that it concatenates a
and b
. Both are potentially right. To come to the correct answer, we need to know what a
and b
are. If a
and b
are numbers, the +
will perform addition, if they are strings - concatenation. The difference between the two is their underlying types.
Note: If you are familiar with JavaScript’s primitive types you may recognize some of the names coming up. The types
string
boolean
andnumber
should feel familiar. These types are the same in TypeScript as they are in JavaScript and are at times referred to as primitive types.
Boolean
boolean
is a type that can only be true
or false
.
let isCarnivore: boolean = true;
let isHerbivore: boolean = false;
Number
number
is used for numbers. If you are familiar with other typed languages, like c++
you may be familiar with specific number types like unsigned int
and float
. In JavaScript and TypeScript, there is only number
.
let teeth: number = 100;
let hex: number = 0xf00d;
String
string
is used for a collection of characters like words.
let name: string = "Leoplurodon";
Literals
In Typescript, there is a subset within string, number, and boolean which allow you to refine the specificity of the type. These are called type literals. A string literal is a single string for example:
type StringLiteralExample = "hello";
If we were to assign a variable to this StringLiteralExample
type we just declared, we would see the only value it can be is "hello"
.
let invalid: StringLiteralExample = "a"; // ERROR
let valid: StringLiteralExample = "hello"; // No issues
What we have done is restricted the string type to be only the single string "hello"
. The same can be done with number
s, and less helpfully, boolean
s. Literals like this are very powerful when used in conjunction with type unions. Allowing us to expand our subset to include multiple values.
type Dinos = "Stegosaurus" | "Triceratops" | "Velociraptor"; //|… any additional dinos

Note: In TypeScript projects and applications using unions like the one above is often used as a low-overhead version of enums.
While we spent the time going over what a literal is. For the remainder of this section (and sections to come), we will not make the distinction between type literals and types since literals are just types.
Array
let list: number[] = [1, 2, 3];
let raptors: Array<string> = ["Blue", "Charlie", "Delta"];
Object
let user: { name: string; age: number } = { name: "Justin", age: 36 };
Note: Later we will learn about Interfaces, which are a better way of describing objects because the description can be reused.
Tuple
let sillyList: [number, string];
sillyList = [5, "boop"]; //typescript is happy
sillyList = ["boop", 5]; //will error
Enum
Enums allow the aliasing of names to a list of numeric values. Like most indexing, enums start their first member at 0.
enum Color {
Red,
Green,
Blue,
}
let greenColor: Color = Color.Green;
Enums can have their first value manually set, or manually set all values
enum Month {
January = 1,
February,
March,
April,
May,
June,
}
let feb = Month[2];
enum Month {
January = 1,
March = 3,
May = 5,
}
let may = Month[5];
Unknown
Unknown describes a variable where we may not know the type. Variables defined with the unknown
type can later be narrowed to more specific types using typeof
checks or comparisons.
Note that variables of type unknown
have no accessible properties or functions.
let value: unknown = 5;
value = "words";
value.length; // Will give "Object is of type unknown" error
// Will give "Type unknown is not assignable to type string" error
const value2: string = value;
// Check type using typeof
if (typeof value === "string") {
// Can successfully narrow
const stringValue: string = value;
console.log("Length is", stringValue.length);
}
Any
Any is useful when you want to opt-out of type checking. Using any
will disable all compile-time checks including access to properties and functions. This is mostly useful for 3rd party data structures that you do not know the shape of, or when incrementally opting in to types.
let my3rdPartyData: any = 5;
my3rdPartyData = "five";
my3rdPartyData.invalidFunction(3); // Will not error until runtime
Void
No type at all - commonly used with functions that don't return a value.
function buttonClick(): void {
console.log("I clicked a button that returns nothing");
}
Null & Undefined
Null and Undefined are two separate types, and subtypes of all other types, meaning they can be assigned to another type like string or number unless the --strictNullChecks flag is used.
Never
The never type represents a value that will never occur.
function error(message: string): never {
throw new Error(message);
}
Type Inference
When we don't provide explicit types for our variables, TypeScript will do its best to infer the types, and it's very good at it. The following code will not compile due to type inference.
let name = "Sally";
let height = 6;
name = height;
//Type 'number' is not assignable to type 'string'
Type can also be inferred from complex objects.
let person = {
name: "Sally",
height: 6,
address: {
number: 555,
street: "Rodeo Drive",
},
};
person.name = "Cecilia";
//works
person.name = 6;
//Type '6' is not assignable to type 'string'.
person.address.number = "five fifty-five";
//Type '"five fifty-five"' is not assignable to type 'number'.
TypeScript will infer the return value of a function as well.
function multiplier(a: number, b: number) {
return a * b;
}
var multiplied: number = multiplier(2, 3);
//works
var str: string;
str = multiplier(10, 20);
//Type 'number' is not assignable to type 'string'.
Type inference can be a very helpful tool in refactoring code and helping better document expectations for our code.
Type assertions
Type assertions are a way to override the inferring of types. There are two different syntaxes, angle-brackets and as.
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
let otherValue: any = "this is a string";
let otherLength: number = (otherValue as string).length;
The as
syntax is usually preferred because the <type>
conflicts with JSX syntax.
Exercise: Fix Type Errors
The Problem
In this exercise, we will learn to spot and correct basic type errors by
fixing the type errors in 2a-fix-errors.ts
:
let isLoading: boolean;
isLoading = true;
isLoading = "false";
let inventory: Array<number> = [];
inventory.push("tacos", "hamburgers");
function greet(name: string, age: number): string {
return `${name} is ${age} years young.`;
}
export const jessica = greet(30, "Jessica");
export const tom = greet("Tom", 42, "software");
export { isLoading, inventory };
What You Need to Know
The exports of 2a-fix-errors.ts
should look like:
it("exports are correct", function () {
assert.equal(isLoading, false, "isLoading");
assert.deepEqual(inventory, ["tacos", "hamburgers"], "inventory");
assert.equal(jessica, `Jessica is 30 years young.`, "jessica");
assert.equal(tom, `Tom is 42 years young.`, "Tom");
});
Verify Your Solution
✏️ Run the following to verify your solution:
npm run 2a-types
The Solution
Click to see the solution
✏️ Update 2a-fix-errors.ts
to look like:
let isLoading: boolean;
isLoading = true;
isLoading = false;
let inventory: Array<string> = [];
inventory.push("tacos", "hamburgers");
function greet(name: string, age: number): string {
return `${name} is ${age} years young.`;
}
export const jessica = greet("Jessica", 30);
export const tom = greet("Tom", 42);
export { isLoading, inventory };
Exercise: Date It
The Problem
In this exercise, we will create our own typed variable by updating 2b-date-export.ts
to:
- Create a
let
variable that takes a type of Date. - Assign that variable to an instance of
Date
- Export that variable as the default export.
What You Need to Know
- Use
new Date()
to create an instance of Date.
Verify Your Solution
✏️ Run the following to verify your solution:
npm run 2b-types
The Solution
Click to see the solution
✏️ Update 2b-date-export.ts
to create, assign, and export a date variable.
let me: Date;
me = new Date("6-11-1993");
export default me;