Types in Typescript :
- number ( 1, 5.3, -10)
- string (“H1”, ‘Hi’)
- boolean (true, false)
- object {age:30}
- Array [1,2,3] – Any Javascript Array
- Tuple. [1,2] (Fixed-length and Fixed type array)
- Enum enum { NEW, OLD } – Automatically enumerated global constant identifiers
- Any * (Any kind of value, no specific type, flexible)
- Union (combining types)
- Literal
- Function
- unknown
- never
The Key difference is : Javascript uses “dynamic types” (resolved at runtime), Typescript uses “static types” (set during development)
Type casting:
In Typescript, you work with types like string or number all the times.
Important: It is string and number (etc.), NOT String, Number etc.
The core primitive types in Typescript are all lowercase!
Let’s consider the example of our (Sum.js) which adds two numbers
// In Javascript
function add (<em>n1</em>, <em>n2</em>) {
return n1 + n2;
}
const number1 = '5';
const number2 = 2.8;
const result = add(number1, number2);
console.log('result', result); // 52.8. (Since n1 is concatenating with n2)
JavaScriptNow this, can be resolved with Typescript
// In Typescript
function add (<em>n1</em>: <em>number</em>, <em>n2</em>: <em>number</em>) {
return n1 + n2;
}
const number1 = 5;
const number2 = 2.8;
const result = add(number1, number2);
console.log('result', result); // 7.8.
JavaScriptObjects
Let’s create a object
// in Javascript
const person = {
name: 'Sujay',
age: 28,
}
console.log(person.name);
console.log(person.age);
JavaScriptTypescript uses Type Inference
// in Typescript
const person: <em>object</em> = {
name: 'Sujay',
age: 28,
}
console.log(person.name); // This will throw error in Typescript since it infers the types of the object
// we can add types for the object like this
const person: {
name: <em>string</em>;
age: <em>number</em>;
} = {
name: 'Sujay',
age: 28,
};
console.log(person.name); // This will be fine.
JavaScriptNested Objects & Types
Of course object types can also be created for nested objects.
Let’s say you have this Javascript Object:
const product = {
id: 'abc',
price: 12.99,
tags: ['great-offer', 'hot-and-new'],
details: {
title: 'Red Carpet',
description: 'A great carpet - almost brand-new!'
}
}
JavaScriptThis would be the type of such an object:
{
id: string;
price: number;
tags: string[];
details: {
title: string;
description: string;
}
}
JavaScriptSo you have an object type in an object type so to say.
Array Types
const person = {
name: 'Sujay',
age: 30,
hobbies: ['Sports', 'Cooking']
};
let favouriteActivites: <em>string</em>[]; // array of strings
favouriteActivites = 'Sports' // this will throw error since its not an array.
favouriteActivites = ['Sports'];
for (const hobby of person.hobbies) {
console.log(hobby.toUpperCase());
}
JavaScriptTuple Types
When you know exactly x amount of values in a array and you know the exact types of each value. then Tuple can be useful.
const person = {
name: string;
age: number;
hobbies: string[],
role: [number, string]; // defining the type of tuple which will be fixed
} = {
name: 'Sujay',
age: 28,
hobbies: ['Sports', 'Cooking'],
role: [2, 'author']
}
console.log(person.role);
JavaScriptEnums
Defining custom enum, whenever you need identifiers that are human readable
enum <em>Role</em> { ADMIN = 'ADMIN', READ_ONLY = 200, AUTHOR = 'AUTHOR' };
const person = {
name: 'Sujay',
age: 30,
hobbies: ['Sports', 'Cooking'],
role: Role.ADMIN
}
JavaScriptAny
any is a flexible type to tell typescript, that the type to infer can be anything. Usually we wanna avoid this as much as possible
const value: <em>any</em> = '334';
JavaScriptUnion
It is used to combine the types, using | (pipe) operator we can declare multiple types
// typescript
// using union type to decribe the type of input1 as it can be number or string using |
function combine(<em>input1</em>: <em>number</em> | <em>string</em>, <em>input2</em>: <em>number</em> | <em>string</em>) {
let result;
if (typeof input1 === 'number' && typeof input2 === 'number') {
result = input1 + input2;
} else {
result = input1.toString() + input2.toString();
}
return result;
}
const combinedAges = combine(30, 23);
console.log(combinedAges) // 53
const combinedNames = combine('Max', 'Anna');
console.log(combinedNames); // MaxAnna
JavaScriptLiteral Types
Literal Types in Typescript are types that constraint the type of a variable to a specific value.
For example, the type "hello world"
represents the string value "hello world"
.
Literal types can be used to specify the exact value for a variable or property, providing precise and self-documenting code.
Here is an example of how literal types can be used to specify the exact value for a variable:
const greeting: <em>string</em> = "hello world";
JavaScriptIn this example, the variable greeting
is assigned the string value "hello world"
. The literal type "hello world"
ensures that the variable greeting
can only be assigned the string value "hello world"
.
Literal types can also be used to specify the exact value for a property.
Here is an example of how literal types can be used to specify the exact value for a property:
interface <em>Person</em> {
name: <em>string</em>;
age: <em>number</em>;
}
JavaScriptIn this example, the interface Person
defines a property name
of type string
and a property age
of type number
. The literal types "John"
and 30
ensure that the properties name
and age
can only be assigned the string value "John"
and the number value 30
, respectively.
Literal types are a powerful tool that can be used to improve the precision and self-documentation of your code.
// typescript (index.ts)
function combine (
<em>input1</em>: <em>number</em> | <em>string</em>,
<em>input2</em>: <em>number</em> | <em>string</em>,
<em>resultConversion</em>: 'as-number' | 'as-text', //literal types
) {
let result;
if (typeof input1 === 'number' && typeof input2 === 'number' || resultConversion === 'as-number') {
result = +input1 + +input2; // converting to numbers before adding
} else {
result = input1.toString() + input2.toString();
}
return result;
}
const combinedAges = combine(30, 26, 'as-number');
console.log('combinedAges', combinedAges);
const combinedStringAges = combine('30', '26', 'as-number');
console.log('combinedStringAges', combinedStringAges);
const combinedNames = combine('Max', 'Anna', 'as-text');
console.log('combinedNames', combinedNames);
JavaScriptType Alias / Custom Types
We can create a new type alias
// typescript (index.ts)
type <em>Combinable</em> = <em>number</em> | <em>string</em>; // custom types
type <em>ConversionDescriptor</em> = 'as-number' | 'as-text'; //literal types
function combine (
<em>input1</em>: <em>Combinable</em>,
<em>input2</em>: <em>Combinable</em>,
<em>resultConversion</em>: <em>ConversionDescriptor</em>,
) {
let result;
if (typeof input1 === 'number' && typeof input2 === 'number' || resultConversion === 'as-number') {
result = +input1 + +input2; // converting to numbers before adding
} else {
result = input1.toString() + input2.toString();
}
return result;
}
const combinedAges = combine(30, 26, 'as-number');
console.log('combinedAges', combinedAges);
const combinedStringAges = combine('30', '26', 'as-number');
console.log('combinedStringAges', combinedStringAges);
const combinedNames = combine('Max', 'Anna', 'as-text');
console.log('combinedNames', combinedNames);
JavaScriptType Aliases & Object Types
Type aliases can be used to “create” your own types. You’re not limited to storing union types though – You can also provide an alias to a (possibly complex) object type.
For example:
type <em>User</em> = { name: <em>string</em>; age: <em>number</em> };
const u1: <em>User</em> = {
name: 'Max', age: 30
};
JavaScriptThis allows you to avoid unnecessary repetition and manage types centrally.
For example, you can simplify this code :
function greet(<em>user</em>: { name: <em>string</em>; age: <em>number</em> }) {
console.log('Hi, I am ' + user.name);
}
function isOlder(<em>user</em>: { name: <em>string</em>; age: <em>number</em> }, <em>checkAge</em>: <em>number</em>) {
return checkAge > user.age;
}
JavaScriptTo:
type <em>User</em> = { name: <em>string</em>; age: <em>number</em> };
function greet(<em>user</em>: <em>User</em>) {
console.log('Hi, I am' + user.name);
}
function isOlder(<em>user</em>: <em>User</em>, <em>checkAge</em>: <em>number</em>) {
return checkAge > user.age;
}
JavaScriptFunction Return Types & “void”
function add (<em>n1</em>: <em>number</em>, <em>n2</em>: <em>number</em>) {
return n1 + n2;
}
// we can add a return type
function add (<em>n1</em>: <em>number</em>, <em>n2</em>:<em>number</em>) : <em>number</em> {
return n1 + n2;
}
// void return type
function printSum(<em>num</em>: <em>number</em>) : <em>void</em> {
console.log('Result' + num); // does not return anything
}
printSum(add(8,8));
JavaScriptWe can’t use undefined
// we can add a return type
function add (<em>n1</em>: <em>number</em>, <em>n2</em>:<em>number</em>) : <em>number</em> {
return n1 + n2;
}
// void return type
// void return type
function printSum(<em>num</em>: <em>number</em>) : <em>void</em> {
console.log('Result' + num); // does not return anything
}
function printSum(<em>num</em>: <em>number</em>) : <em>undefined</em> {
console.log('Result' + num);
return; // this won't throw any error, but will throw error if you remove the return
}
JavaScriptFunction as Types
Function types defines the parameters and return type of a function.
// we can add a return type
function add (<em>n1</em>: <em>number</em>, <em>n2</em>:<em>number</em>) : <em>number</em> {
return n1 + n2;
}
// void return type
function printSum(<em>num</em>: <em>number</em>) : <em>void</em> {
console.log('Result' + num); // does not return anything
}
printResult(add(5,12));
let combineValues: (<em>a</em>: <em>number</em>, <em>b</em>: <em>number</em>) => <em>number</em>; // Function Type parameters with return type
combineValues = add; // this is fine
combineValues = printResult; // this throws error, since our arguments doen't match the types
console.log('combineValues', combineValues(8, 8));
JavaScriptFunction Types & Callbacks
// we can add a return type
function add (<em>n1</em>: <em>number</em>, <em>n2</em>:<em>number</em>) : <em>number</em> {
return n1 + n2;
}
function printResult(<em>num</em>: <em>number</em>) : <em>void</em> {
console.log('Result: ' + num);
}
function addAndHandle(<em>n1</em>: <em>number</em>, <em>n2</em>: <em>number</em>, cb: (<em>num</em>: <em>number</em>) => <em>void</em>) { // function type def
const result = n1 + n2;
cb(result); //pass it to callback function
}
printResult(add(5, 12));
addAndHandle(10, 20, (<em>result</em>) => {
console.log('callback result', result);
});
JavaScriptWhich code snippet is better (i.e. which code should you write) ?
1. function sayHi(): <em>void</em> {
//...
}
OR
2. function sayHi(): <em>undefined</em> {
// ...
}
=> 1. because it doesn't force you to return anything if you don't want to return something.
JavaScriptWill this code compile ?
function sendRequest(<em>data</em>: <em>string</em>, cb: (<em>response</em>: <em>any</em>) => <em>void</em>) {
// ...sending a request with "data"
return cb({data: 'Hi there!'});
}
sendRequest('Send this!', (<em>response</em>) => {
console.log(response);
return true;
});
JavaScriptYes! As callback functions can return something, even if the argument on which they’re passed does NOT expect a returned value.
unknown
unknown is a better choice than any, need to do a extra type checking
let userInput: <em>unknown</em>;
let userName: <em>string</em>;
userInput = 5;
userInput = 'Max';
if (typeof userInput==='string') {
userName = userInput
}
JavaScriptnever
never is used when we know the function that never returns anything.
function generateError(<em>message</em>: <em>string</em>, <em>code</em>: <em>number</em>): <em>never</em> { // return type is never since it never returns anything
throw { message: message, errorCode: error };
}
const result = generateError('An error occurred!', 500);
console.log('result', result); // never returns not even undefined
JavaScript