Introduction to TypeScript
TypeScript is a strongly typed programming language that builds on JavaScript, adding optional static typing to catch errors at compile-time instead of runtime. This makes your code more robust and easier to maintain.
TypeScript is a programming language that adds optional static typing to JavaScript. This means that you can specify the types of variables, objects, function parameters, and function return values in your code. With TypeScript, you can catch type-related errors at compile-time instead of waiting until runtime.
For example, let's say you have a function that takes in two arguments, x
and y
, and returns their sum:
function add(x, y) {
return x + y
}
In JavaScript, this function would work fine if you pass in two numbers as arguments. However, if you accidentally pass in a string or another non-numeric value, you would get unexpected results or even errors at runtime.
With TypeScript, you can add type annotations to the function parameters and return value to ensure that they are always numbers:
function add(x: number, y: number): number {
return x + y
}
Now, if you try to pass in a non-numeric value, you would get a compile-time error, preventing any runtime errors from occurring.
This is just one example of how TypeScript can help catch errors at compile time and make your code more robust and maintainable.
If you know JavaScript, learning TypeScript should be easy.
To configure TypeScript environment, click here.
Type System
Type System allows developers to specify the type of a variable or function parameter. TypeScript includes different types, such as any, void, never, unknown
, that can be used to define the type of a variable or function parameter.
TypeScript has the following types:
- Primitive Types
- String
- Number
- Boolean
- Null
- Undefined
- Void
- Never
- Object Types
- Array
- Function
- Object
- Special Types
- Any
Type Annotation
Type annotation in TypeScript is a feature that allows developers to specify the type of a variable, function parameter, or function return value. This is done by adding a colon (:
) followed by the desired type after the variable or parameter name.
To put it plainly, type annotations in TypeScript are a way to indicate the type of value that a variable will hold. We do this by explicitly stating the type of a variable, which is called an annotation.
Let’s look at some examples of type annotation.
Variable
const color: string = 'Purple'
const age: number = 25
const isLucky: boolean = true
const nothingMuch: undefined = undefined
const nothing: null = null
In the code snippet above, you will find different examples of type annotations for variables. By explicitly stating a type using the :
syntax, TypeScript guarantees that the variable will only store a value of the specified type.
Array
Array annotation in TypeScript is a feature that allows developers to specify the type of an array and its elements. To annotate an array in TypeScript, you can use the syntax type[]
, where type
is the type of the array elements. For example, to create an array of strings in TypeScript, you can use the following syntax:
const colors: string[] = ['red', 'green', 'blue']
In this example, colors
is an array of strings. You can also create arrays of other types, such as numbers or booleans, by changing the type after the :
. For example:
const evens: number[] = [2, 4, 6, 8, 10]
const isLucky: boolean[] = [true, false, false, true]
Function
Function annotation allows developers to specify the type of parameters a function will receive and the type of value a function will return. For example, to create a function that will accept two numbers and return their sum, you can use the following syntax:
const add = (a: number, b: number): number => a + b
function add(a: number, b: number): number {
return a + b
}
If a function does not return anything then you can mention void
as a return type. Technically, you can return undefined
from a void
function.
In some rare cases, a function may never terminate and reach its end. This might happen when a function throws some exception. For example,
const throwSomeException = (message: string): never => {
throw new Error(message)
console.log(message)
}
In the above example, the function will never reach its end because it will exit after throwing an exception hence will never return anything. TypeScript has a never
type that can be useful in such scenarios.
Object
Object annotation allows a developer to specify types for different object properties and methods.
const person = {
name: 'John',
age: 20,
}
The person
object in the above code snippet has two properties. The name
property stores the name of a person and age
property stores the age of a person.
In JavaScript, you can assign a string value to an age
property like this,
person.age = '20'
The above code snippet will assign a '20'
string value to the age property hence changing the type of data stored in the property from a number to a string. These types of cases might create bugs in your code. To prevent this, you can add types to objects.
const person: { name: string; age: number } = {
name: 'John',
age: 20,
}
The above code will ensure that the name
variable will only refer to string type values and the age
variable will only refer to number type values. If you try to assign any different types then TypeScript will throw an error.
The TypeScript object notation syntax can be improved using Type
or Interface
notation.
interface IPerson {
name: string
age: number
}
const person: IPerson = {
name: 'John',
age: 20,
}
As you can see in the above code snippet, you can create an interface for object type and use it for annotation to improve readability. The interface only contains a declaration of object properties and methods.
Type Inference
In type annotation, you have to explicitly specify types for a variable, function, or object. In some cases, it is not necessary to annotate types as TypeScript is smart enough to guess the type from the value. This is called Type Inference.
In Type Inference, TypeScript tries to guess the type of a variable from the specified value.
Type inference only works in the following scenarios:
- When variables are initialized.
- When default values are set for parameters.
- Function return types are determined.
If variable declaration and initialization are done on the same line, TypeScript infers the type of a value automatically without giving annotation.
If initialization is done after declaration then TypeScript inference does not work. It infers type as any.
let someNumber = 3
In the above example, variable someNumber
is initialized to value 3
hence TypeScript will automatically infer the type as a number without you specifying the type annotation.
let someNumber // Infers as any
someNumber = 3
It also works in the case of functions.
const add = (a: number, b: number) => a + b
In the above example, since type annotation for parameters is specified there is no need to specify the function return type as TypeScript will automatically infer the return type to a number.
Even though, TypeScript is smart enough to infer function return type. It is always good to annotate the function’s return type. Let’s see this with the help of an example.
function subtract(a: number, b: number) {
a - b
}
In the above example, the subtract function is not returning anything hence the return type is inferred as void
, but the function is expected to return a value of type number. If you add a number as a return type to the above function then TypeScript will throw an error. In this way, you can avoid any runtime bugs in your code using TypeScript.
function subtract(a: number, b: number): number {
a - b
}
When to use it?
Type Annotation | Type Inference |
---|---|
Use it when a variable is declared first and initialized later. | Use it always and wherever possible. |
Use it when the return type is inferred as any and a specific type needs to be returned. | |
Use when TypeScript cannot infer the correct type. |
TL;DR
- TypeScript is a superset of JavaScript that allows to catch errors during development or compile time rather than waiting till run time.
- TypeScript’s type system provides primitive types like
string, number, boolean, void
,etc., and object types likefunctions, array, object
,etc. - In type annotation, you have to specify types of a variable, function parameters, or object.
- In type inference, TypeScript tries to guess the type of a variable.
Top comments (2)
a) How do you 'accidentally' pass anything in? YOU are in control of the program and its inputs. It just does what you tell it to.
b) The results should not be unexpected, as JS behaves in a predictable way. They're only unexpected if you do not understand JS
Thank you Jon for your comment. I agree that the programmer has control over the program and its inputs. However, mistakes can happen, leading to invalid inputs.
For instance, in the
add
function in JavaScript, a user may mistakenly input non-numeric data or just mess with the form input and type anything, resulting in runtime errors or incorrect outputs. This issue can be avoided by implementing proper validation checks as well but I wanted to mention this example in the context of TypeScript.Thank you again for your input.