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); // MaxAnnaJavaScriptLiteral 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