Learn TypeScript in Construct, part 5: More about types

UpvoteUpvote 4 DownvoteDownvote

Index

Features on these Courses

Stats

134 visits, 176 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY-NC 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Published on 27 Jun, 2025.

The 'any' type

TypeScript also provides a special type named any. This can be assigned any value at all.

// Declare a variable with the special 'any' type
let value: any;

// Assigning a string: OK
value = "Hello world!";

// Assigning a number: OK
value = 123;

This basically disables type checking completely. You can do things like assign an any type value to a number, and TypeScript allows it.

let value: any = "hello";

// Allowed - but wrong!
let num: number = value;

You might notice this means num ends up holding a string, even though it is declared as holding a number. If this happens it breaks the assumptions the rest of your code makes and it may well result in an error when running the code. This makes it quite a dangerous feature and it rather defeats the purpose of using TypeScript. However it's worth knowing because sometimes TypeScript resorts to the any type if it doesn't know what type something is. For example TypeScript actually allows declaring a variable with no type, which defaults to any:

// This:
let value;

// is the same as:
let value: any;

As noted, try to avoid doing that. However when you get in to more advanced code, it's worth knowing about, as in some rare cases it can be useful to actually treat something as the any type.

The 'unknown' type

A related type is unknown. This is similar to any, but it does actually have some checks, like preventing you from assigning it to a different type.

// Variable uses 'unknown' type
let value: unknown = "hello";

// Now this is not allowed
let num: number = value;

You could allow assigning to num if you first check typeof value === "number" in an if statement. As we saw before that uses type narrowing, and TypeScript then knows inside the if statement the value really is a number. That means unknown is a safer option than any if you really do want a variable that can hold anything, as TypeScript will force you to check the type of it when you use it, as opposed to allowing you to do anything with it.

The 'never' type

There is one more special type to cover here. Suppose you have the code below. What is the type of num inside the if statement?

let num = 123;

if (typeof num === "string")
{
	console.log(num);
}

TypeScript knows that num is a number, so it will never be a string. TypeScript still needs a type to represent what num could be inside the if statement though. Type narrowing means it knows it's not a number, but it also knows it's not a string. In this case TypeScript uses the type never, indicating there is no valid type to fulfil the requirement.

Undefined

TypeScript also has a special value undefined which is used to represent an empty value - for example a variable that stores nothing, rather than any particular string, number, or anything else. You can use this to make an "optional" variable that either holds a value, or nothing.

// Either holds a number, or undefined.
let value: number | undefined = 123;

// You can assign the special value 'undefined' as well.
value = undefined;

// This will log: undefined
console.log(value);

typeof will return the string "undefined" when a value is set to the special undefined value.

let value: number | undefined = 123;

if (typeof value === "undefined")
{
	// The value is not set
	console.log("Value is undefined");
}
else
{
	// The value is set to a number
	console.log(value);
}

Note that type narrowing works in the else statement as well. In other words TypeScript uses the typeof check to eliminate the possibility that value is undefined, and therefore it must be a number in the else block.

undefined is also a falsy value. If you use it in an if statement by itself, it works the same as false. Remember that both 0 and an empty string are falsy as well though!

Using optional values like this is very common in programming, and we'll come back to this later. It's generally useful to have a distinct value that means "nothing" or "not set" as opposed to an actual value. It might be tempting to use a special value like 0 or -1 to represent a number that is not set, but in some cases all possible numbers would be valid to be set, and so it's generally a better idea to use a different type of value to represent the empty state.

null

Rather confusingly, there is a second empty value in TypeScript: null. Like undefined it can be used as both a type and a value, and is falsy if used in an if statement. Why does it exist? TypeScript inherits both undefined and null from JavaScript, and JavaScript having two special empty values is widely regarded as a design mistake. It's too late to change it, so unfortunately it's just a slightly weird thing we have to live with.

Generally undefined is the empty value used by the JavaScript language itself. Construct-specific features (which we'll get on to later) generally use null. The difference doesn't matter much - in many cases it won't affect the code you write.

One other quirk to be aware of is typeof null is "object". This is also widely regarded as a mistake - it would make more sense if it was "null". Unfortunately this is another thing that's too late to change. Oops! If you ever design a programming language, be sure to think through the design very carefully!

  • 0 Comments

Want to leave a comment? Login or Register an account!