Hey TECHIE curious about TypeScript's ?
Let's explore the world of types together, unraveling their importance and how they make your code stronger.
There are various types available in Typescript
String
It represents the string value like
"Hello World"
const welcomeMessage: string = "Hello World";
The beauty of TypeScript is that when you use the variable
welcomeMessage
it provides only those methods that are available in String, other methods are automatically get narrow down
Number
It Represents Numbers like
42, 10, 52.33
There are NO Integer or Float values, They are just Numbers
const userId: number = 123;
Boolean
It Represents True / False
const isLoggedIn: boolean = false;
Array
There are multiple ways to define an Array
const users: string[] = []; // Array of Strings const userIds: number[] = []; // Array of Numbers const usersInfo:Array<number> = []; // Arrays of Numbers
Any
Any is a kind of getaway, where you do not let the type/ static checking
Any should be avoided in most of the cases
Any simply means turn off the checking for this particular instance
It is like you are making your code more JavaScript manner
let myName; function printName() { return true; // We can return string, number, anything (NO ONE IS STOPPING US) } myName = printName(); // myName is of Type any // PrintName function can return anything to us.... // It could be string, number, etc
Interestingly, Typescript offers a method that prevents us from using any
Method is noImplicitAny
In the TS config file, we can add a flag noImplicitAny
Use the compiler flag
noImplicitAny
to flag any as an error
Functions
Functions are the heart and soul of Programming
In most cases, types are inferred from the parent, but not in the case of Functions
Apart from function, Typescript is smart info to infer the type
-
In Functions, typescript can't infer the type
// WHEN WE ARE NOT USING TYPE EXAMPLE - 1 function addNumber(value) { return value + 5; return "abc" return false // We can return a string, a number, a boolean, Therefore perfroming any operation based on the return is not possible } addNumber("Ankush"); addNumber(true) // We can Pass anthing in the Parameters, NO ONE IS STOPPING US // This is very bad when it comes to big end application EXAMPLE-2 function upperCase(value){ return value.toUpperCase() /* STRING method */ return value.toFixed() /* NUMBER method */ } upperCase(30); upperCase(true); // Here we are using String & Number Methods on the same value which will definitely cause an break in the application
Suppose You've got a function that's the backbone of your code. Everything depends on its result. But if someone changes its return type by mistake, your whole program breaks down
To address this issue, we utilize TypeScript.
By doing so, the next developer who works on the code understands that this particular function is expected to return a numerical value.
// WHEN WE ARE USING TYPESCRIPT EXAMPLE - 1 function addNumber(value:number): number { return value + 5; } addNumer(10) // Here value should be number and Type should also be number // MUCH BETTER code as compared to previous one, We know the parameter and return Type EXAMPLE-2 function upperCase(value: string) : string { // We can also access those function that are present in the String return value.toUpperCase() } upperCase("ankush") // FUNCTION WHICH RETURN PROMISE async function getFavoriteNumber(): Promise<number> { return 26; }
Objects
// creating a type of CreditCard
type creditCard = {
last4: number;
expiryDate: string;
cvv: number;
isPremiumMember: boolean;
};
// creating a type of user
type User = {
readonly _id: string; /* You cannot Change Read Only */
name: string;
email: string;
isActive: boolean;
creditCardDeatils?: creditCard; /* ? stands for => for Optional */
entireCardDetails?: entireCardDetails;
};
// Optional Parameters are not Mandatory
// Implementing the user type
let NewUser: User = {
_id: "123",
name: "ankush",
email: "ankush@ankush.com",
isActive: true,
};
NewUser.email = "ankush@gmail.com";
// NewUser._id = "56565"; we cannot change the ID
Learnings:
We can create type using the keyword
type
readonly_id
=> User is not allowed to change the value?
stands for Optional ParameterOptional Parameters are not mandatory
when you read from an optional property, you’ll have to check for undefined before using it, because if you access a property that doesn’t exist you’ll get the value undefined rather than a runtime error.
function printName(obj: { first: string; last?: string }) { // Error - might crash if 'obj.last' wasn't provided! console.log(obj.last.toUpperCase()); 'obj.last' is possibly 'undefined'. if (obj.last !== undefined) { // OK console.log(obj.last.toUpperCase()); } // A safe alternative using modern JavaScript syntax: console.log(obj.last?.toUpperCase()); }
Union
It is a way of combining types
A union type is a type formed from two or more other types
Union represents with Pipe Symbol ->
|
function printId(id: number | string) { console.log("Your ID is: " + id); } // OK printId(101); // OK printId("202"); // Error printId({ myID: 22342 }); Argument of type '{ myID: number; }' is not assignable to parameter of type 'string | number'.
Most Important point
TypeScript will only allow an operation if it is valid for every member of the union
For example, if you have the union
string | number
, you can’t use methods that are only available onstring
:function printId(id: number | string) { console.log(id.toUpperCase()); Property 'toUpperCase' does not exist on type 'string | number'. Property 'toUpperCase' does not exist on type 'number'. }
The solution is to narrow the union with code, the same as you would in JavaScript without type annotations.
function printId(id: number | string) { if (typeof id === "string") { // In this branch, id is of type 'string' console.log(id.toUpperCase()); } else { // Here, id is of type 'number' console.log(id); } } // YOU NEED TO CHECK THE TYPE, because at the top you have specified the type as Union
Type Assertions
Sometimes you will have a value that TypeScript can’t know about.
For example, if you’re using
document.getElementById
, TypeScript only knows that this will return some kind ofHTMLElement
, but you know that your page will always have anHTMLCanvasElement
with a given ID.then we can use type assertion to specify a more specific type:
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement; // Another way const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
Like a type annotation, type assertions are removed by the compiler and won’t affect the runtime behavior of your code. You can also use the angle-bracket syntax
Literal Types
In addition to the general types
string
andnumber
, we can refer to specific strings and numbers in type positions.let x: "hello" = "hello"; // OK x = "hello"; // ... x = "howdy"; Type '"howdy"' is not assignable to type '"hello"'.
It’s not much use to have a variable that can only have one value!
But by combining literals into unions, you can express a much more useful concept - for example, functions that only accept a certain set of known values
function printText(s: string, alignment: "left" | "right" | "center") { // ... } printText("Hello, world", "left"); printText("G'day, mate", "centre"); Argument of type '"centre"' is not assignable to parameter of type '"left" | "right" | "center"'.
Thank you for your valuable time. I hope this article is helpful in some way. Please feel free to leave your valuable comments.