Typescript – Using Types

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)
JavaScript

Now 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. 
JavaScript

Objects

Let’s create a object

// in Javascript
const person = {
  name: 'Sujay',
  age: 28,
}
console.log(person.name); 
console.log(person.age);
JavaScript

Typescript 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.
JavaScript

Nested 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!'
  }
}
JavaScript

This would be the type of such an object:

{
  id: string;
  price: number;
  tags: string[];
  details: {
    title: string;
    description: string;
  }
}
JavaScript

So 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());
}
JavaScript

Tuple 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);
JavaScript

Enums

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
}
JavaScript

Any

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';
JavaScript

Union

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
JavaScript

Literal 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";
JavaScript

In 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>;
}
JavaScript

In 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);
JavaScript

Type 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);
JavaScript

Type 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
};
JavaScript

This 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;
}
JavaScript

To:

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;
}
JavaScript

Function 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));
JavaScript

We 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
}
JavaScript

Function 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));
JavaScript

Function 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);
});
JavaScript

Which 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.
JavaScript

Will 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;
});
JavaScript

Yes! 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
}
JavaScript

never

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

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *