TypeScript | Beginner

TypeScript | Beginner

Hello my fellow frontend, backend and fullstack developer, today i will be covering some beginner Typescript concepts with examples.
Let’s get started…

1) Introduction to TypeScript
TypeScript is a superset of JavaScript that adds static typing to the language. It helps catch errors at compile time and provides better code organization.

function greet(name: string) {
return `Hello, ${name}!`;
}
console.log(greet(Alice));

Tips and Tricks: Use TypeScript to define types for variables, functions, and more to improve code reliability.

Best Use Cases: Ideal for large-scale applications where type safety is crucial.

2) Basic Types
TypeScript includes basic types such as number, string, boolean, array, etc.

let age: number = 25;
let name: string = Bob;
let isStudent: boolean = true;
let numbers: number[] = [1, 2, 3, 4, 5];

Tips and Tricks: Use type inference to let TypeScript automatically determine the type when possible.

Best Use Cases: Used for defining simple data types in your code.

3) Interfaces
Interfaces define the structure of an object in TypeScript.

interface Person {
name: string;
age: number;
}
function greet(person: Person) {
return `Hello, ${person.name}!`;
}

Tips and Tricks: Interfaces help enforce a consistent shape across objects.

Best Use Cases: Useful for defining data contracts in your application.

4) Classes
Classes in TypeScript allow you to use object-oriented programming concepts like inheritance and encapsulation.

class Animal {
constructor(public name: string) {}
move(distance: number) {
console.log(`${this.name} moved ${distance} meters.`);
}
}

Tips and Tricks: Use access modifiers like public, private, and protected for better encapsulation.

Best Use Cases: Great for modeling real-world entities in your code.

5) Generics
Generics allow you to create reusable components that can work with a variety of data types.

function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>(hello);

Tips and Tricks: Use generics when you want a function or class to work with any data type.

Best Use Cases: Helpful for creating flexible and reusable code.

6) Enums
Enums in TypeScript allow you to define a set of named constants.

enum Direction {
Up,
Down,
Left,
Right
}
let heading: Direction = Direction.Up;

Tips and Tricks: Enums help make your code more readable by giving friendly names to numeric values.

Best Use Cases: Useful when you have a set of related constants.

7) Type Assertion
Type assertion is a way to tell the compiler about the type of a variable when TypeScript can’t infer it.

let input: any = hello;
let length: number = (input as string).length;

Tips and Tricks: Use type assertion when you know more about a value than TypeScript does.

Best Use Cases: Helpful when working with data from external sources.

8) Decorators
Decorators are a special kind of declaration that can be attached to classes, methods, accessors, properties, or parameters.

function log(target: any, key: string) {
console.log(`Method ${key} called`);
}
class Example {
@log
someMethod() {
// Method implementation
}
}

Tips and Tricks: Decorators are widely used in frameworks like Angular for metadata reflection.

Best Use Cases: Useful for adding metadata to classes and members.

9) Modules
Modules in TypeScript help organize code into reusable units.

// math.ts
export function add(a: number, b: number): number {
return a + b;
}
// app.ts
import { add } from ./math;
console.log(add(2, 3)); // Output: 5

Tips and Tricks: Use modules to keep your codebase clean and maintainable.

Best Use Cases: Essential for structuring large applications.

10) Namespaces
Namespaces allow you to organize code by grouping logically related objects.

namespace Geometry {
export class Circle {
// Circle implementation
}
}
let circle = new Geometry.Circle();

11) Type Inference
Type inference in TypeScript allows the compiler to determine types when they’re not explicitly specified.

let num = 10; // TypeScript infers the type as number

Tips and Tricks: TypeScript’s type inference can save time and make the code cleaner.

Best Use Cases: Useful for writing concise code without sacrificing type safety.

12) Type Guards
Type guards allow you to narrow down the type of a variable within a conditional block.

function isNumber(x: any): x is number {
return typeof x === number;
}
if (isNumber(value)) {
// Inside this block, TypeScript knows ‘value’ is a number
}

Tips and Tricks: Type guards are helpful when dealing with union types.

Best Use Cases: Useful for working with complex or dynamic data types.

13) Union Types
Union types allow a variable to have multiple types.

let result: number | string;
result = 10; // Valid
result = error; // Also valid

Tips and Tricks: Use union types to handle different scenarios for a variable.

Best Use Cases: Great for representing diverse data types.

14) Intersection Types
Intersection types allow combining multiple types into one.

type A = { a: number };
type B = { b: string };
type C = A & B; // C has both a number property and a string property

Tips and Tricks: Intersection types are useful for combining different types for complex scenarios.

Best Use Cases: Helpful for creating complex data structures.

15) Type Aliases
Type aliases allow you to create a name for any data type.

type Age = number;
let userAge: Age = 25;

Tips and Tricks: Use type aliases to give descriptive names to complex types.

Best Use Cases: Useful for improving code readability and maintainability.

16) Triple-Slash Directives
Triple-slash directives are single-line comments containing a single XML tag.

/// <reference path=”myModule.d.ts” />

Tips and Tricks: Triple-slash directives are often used to declare dependencies between files.

Best Use Cases: Useful when working with modules and declaration files.

17) Type Checking JavaScript Files
TypeScript can be used to check and type-check JavaScript files.

// @ts-check
let num: number = not a number; // TypeScript will throw a type error

Tips and Tricks: Type checking JavaScript files can catch bugs and improve code quality.

Best Use Cases: Useful for gradually migrating a JavaScript codebase to TypeScript.

18) Type Inference for Destructured Objects
TypeScript can infer types for destructured objects.

let person = { name: Alice, age: 30 };
let { name, age } = person; // TypeScript infers the types of ‘name’ and ‘age’

Tips and Tricks: Type inference for destructured objects can save time and reduce redundancy.

Best Use Cases: Helpful for working with complex data structures.

19) Conditional Types
Conditional types in TypeScript allow you to create types that depend on other types.

type NonNullable<T> = T extends null | undefined ? never : T;
type StringOrNumber = string | number;
type NonNullableStringOrNumber = NonNullable<StringOrNumber>; // Result: string | number

Tips and Tricks: Conditional types are powerful for creating flexible and conditional type definitions.

Best Use Cases: Useful for creating generic types that depend on conditions.

20) Mapped Types
Mapped types in TypeScript allow you to create new types from existing types.

type Flags = {
option1: boolean;
option2: boolean;
};
type NullableFlags = { [K in keyof Flags]: Flags[K] | null }; // Result: { option1: boolean | null, option2: boolean | null }

Tips and Tricks: Mapped types are useful for transforming existing types into new ones.

Best Use Cases: Helpful for creating variations of existing types.

21) Declaration Merging
Declaration merging in TypeScript allows combining multiple declarations for the same entity.

interface User {
name: string;
}
interface User {
age: number;
}
let newUser: User = { name: Alice, age: 30 };

Tips and Tricks: Declaration merging is useful for extending existing types without modifying them directly.

Best Use Cases: Helpful for adding functionality to third-party libraries.

22) Type Guards with Classes
Type guards can also be used with classes to narrow down the type of an instance.

class Animal {
move() {
console.log(Moving…);
}
}
class Dog extends Animal {
bark() {
console.log(Woof!);
}
}
function isDog(animal: Animal): animal is Dog {
return (animal as Dog).bark !== undefined;
}

Tips and Tricks: Type guards with classes are useful for handling polymorphic behavior.

Best Use Cases: Great for dealing with inheritance and polymorphism.

23) Tuple Types
Tuple types in TypeScript allow expressing an array where the type of a fixed number of elements is known.

let coordinates: [number, number] = [10, 20];

Tips and Tricks: Use tuple types when working with fixed-length arrays with known element types.

Best Use Cases: Useful for representing structured data like coordinates, RGB values, etc.

24) Index Signatures
Index signatures allow defining how objects can be indexed.

interface StringArray {
[index: number]: string;
}
let myArray: StringArray = [a, b, c];

Tips and Tricks: Index signatures are useful for working with objects that behave like arrays.

Best Use Cases: Helpful for dealing with dynamic data structures.

25) Type Guards with typeof and instanceof
Type guards can be created using the typeof and instanceof operators.

function logValue(value: string | number) {
if (typeof value === string) {
console.log(value.toUpperCase());
} else if (value instanceof Number) {
console.log(value.valueOf());
}
}

Tips and Tricks: Use typeof for primitive types and instanceof for checking instances of classes.

Best Use Cases: Useful for checking specific types in conditional blocks.

26) Recursive Types
TypeScript supports defining recursive types where a type refers to itself.

interface TreeNode {
value: string;
children: TreeNode[];
}

Tips and Tricks: Recursive types are useful for representing hierarchical data structures.

Best Use Cases: Great for modeling tree-like data.

27) String Literal Types
String literal types allow defining a type that can only have specific string values.

type Direction = up | down | left | right;
let move: Direction = up;

Tips and Tricks: String literal types help create specific and concise type definitions.

Best Use Cases: Useful for representing a fixed set of string values.

28) Namespace Merging
Namespace merging allows extending existing namespaces across multiple files.

// math.ts
namespace Math {
export function subtract(a: number, b: number): number {
return a b;
}
}
// extendedMath.ts
namespace Math {
export function multiply(a: number, b: number): number {
return a * b;
}
}

Tips and Tricks: Namespace merging is useful for adding functionality to existing namespaces.

Best Use Cases: Helpful for modularizing code across multiple files.

29) Type Predicates
Type predicates are functions that return a type predicate to narrow down the type within a conditional block.

function isString(value: any): value is string {
return typeof value === string;
}
if (isString(input)) {
console.log(input.toUpperCase());
}

Tips and Tricks: Type predicates are useful for creating reusable type narrowing functions.

Best Use Cases: Great for handling complex type checks.

30) Inference and Strict Mode
TypeScript’s strict mode enables additional type checking options to catch more errors.

// @ts-check
let num: number = not a number; // TypeScript in strict mode will throw a type

31) Type Guards with in Operator
Type guards can also be created using the in operator to check for the existence of a property in an object.

function hasName(obj: any): obj is { name: string } {
return name in obj;
}
if (hasName(user)) {
console.log(user.name);
}

Tips and Tricks: The in operator is useful for checking the presence of properties dynamically.

Best Use Cases: Helpful for checking object properties in a type-safe manner.

32) Type Inference for Arrays
TypeScript can infer the type of arrays based on the elements assigned to them.

numbers = [1, 2, 3]; // TypeScript infers ‘numbers’ as number[]

Tips and Tricks: Type inference for arrays can simplify code and improve readability.

Best Use Cases: Useful for working with arrays of known elements.

33) Promises and Async/Await
TypeScript supports Promises and the async/await syntax for handling asynchronous operations.

function fetchData(): Promise<string> {
return new Promise(resolve => {
setTimeout(() => {
resolve(Data fetched!);
}, 2000);
});
}
async function fetchDataAsync() {
const data = await fetchData();
console.log(data);
}

Tips and Tricks: Promises and async/await are essential for handling asynchronous code in a synchronous-like manner.

Best Use Cases: Great for managing asynchronous operations in a readable way.

34) Generics Constraints
Generics constraints allow restricting the types that can be used with a generic type parameter.

function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}

Tips and Tricks: Generics constraints ensure type safety and provide more specific information to TypeScript.

Best Use Cases: Useful for working with generic types in a controlled way.

35) Type Inference for Default Values
TypeScript can infer types based on default values assigned to variables.

message = Hello, World!; // TypeScript infers ‘message’ as string

Tips and Tricks: Type inference for default values can be convenient for initializing variables without explicitly specifying types.

Best Use Cases: Useful for reducing verbosity in code and allowing TypeScript to infer types based on initial values.

THANK YOU FOR CHECKING THIS POST
You can contact me on –
Instagram – https://www.instagram.com/supremacism__shubh/
LinkedIn – https://www.linkedin.com/in/shubham-tiwari-b7544b193/
Email – shubhmtiwri00@gmail.com

You can help me with some donation at the link below Thank you👇👇
☕ –> https://www.buymeacoffee.com/waaduheck <–

Also check these posts as well

Leave a Reply

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