Most React bugs aren't logic errors. They're state shape errors. ⚠️ The type allowed it. And nobody caught it until production. 𝗛𝗲𝗿𝗲'𝘀 𝘄𝗵𝗮𝘁 𝗺𝗼𝘀𝘁 𝗧𝘆𝗽𝗲𝗦𝗰𝗿𝗶𝗽𝘁 𝘀𝘁𝗮𝘁𝗲 𝗹𝗼𝗼𝗸𝘀 𝗹𝗶𝗸𝗲: interface RequestState { isLoading: boolean; data?: User; error?: string; } This type allows impossible states: ● isLoading: true AND data: User at the same time ● error: "failed" AND data: User at the same time ● isLoading: false with no data and no error — what just happened? setState({ isLoading: false, data: undefined, error: undefined }); UI shows nothing. No loading. No error. Just a blank screen. Your UI is now guessing which state is real. 𝗗𝗶𝘀𝗰𝗿𝗶𝗺𝗶𝗻𝗮𝘁𝗲𝗱 𝘂𝗻𝗶𝗼𝗻𝘀 𝗲𝗹𝗶𝗺𝗶𝗻𝗮𝘁𝗲 𝘁𝗵𝗲 𝗴𝘂𝗲𝘀𝘀𝗶𝗻𝗴: type RequestState = | { status: 'idle' } | { status: 'loading' } | { status: 'success'; data: User } | { status: 'error'; error: string } Now impossible states are actually impossible. data only exists on success. error only exists on error. TypeScript enforces it — not your runtime checks. 𝗨𝘀𝗶𝗻𝗴 𝗶𝘁 𝗶𝗻 𝗮 𝗰𝗼𝗺𝗽𝗼𝗻𝗲𝗻𝘁: switch (state.status) { case 'loading': return <Spinner />; case 'error': return <Error message={state.error} />; case 'success': return <Dashboard data={state.data} />; default: return null; } No optional chaining. No data?.user?.name. No undefined checks. The compiler already knows what exists at each branch. ⚠️ Boolean flags scale poorly. State machines don't. 🎯 𝗧𝗵𝗲 𝗧𝗮𝗸𝗲𝗮𝘄𝗮𝘆 The goal of TypeScript isn't to describe what your data looks like. It's to make wrong states unrepresentable. 💬 What's a bug you hit because your state allowed something impossible? Drop it below. 👇 #TypeScript #SoftwareEngineering #WebDev #FrontendEngineering #ReactJS
Shailesh Parmar’s Post
More Relevant Posts
-
If your TypeScript type has three optional fields that are "never all set at the same time" — that's not a type, that's a verbal agreement. { data?: User; error?: Error; loading?: boolean } Three optional fields allow 8 possible combinations. Only 3 are valid: loading, success, or error. TypeScript cannot catch the other 5 because you never described what valid looks like. // Optional fields — 8 states, 5 are invalid type AsyncState = { data?: User; error?: Error; loading?: boolean; }; // loading + data? Valid TypeScript. Runtime bug. // error + data? Valid TypeScript. Undefined behavior. A discriminated union cuts this to exactly the states you intend: type AsyncState = | { status: 'idle' } | { status: 'loading' } | { status: 'success'; data: User } | { status: 'error'; error: Error }; Now TypeScript knows: if status === 'success', data exists. In the loading branch, accessing data is a compile error. Every switch is exhaustive-checked automatically. This pattern predates TypeScript. Richard Feldman's 2016 Elm talk "Making Impossible States Impossible" named the principle. XState, Redux Toolkit, and React Query all encode state as discriminated unions internally for exactly this reason. When this doesn't apply: • Simple on/off boolean flags — a single boolean is not an "impossible state" problem • React Query's useQuery already returns a discriminated shape — don't rewrap it • Config objects where fields are genuinely independent of each other The "60% fewer runtime errors" stat that circulates online is unsourced. The real benefit is compile-time exhaustiveness checking — TypeScript tells you which cases you haven't handled before you ship. Are you modeling async state with optional fields, or with unions that make invalid states impossible to represent? #TypeScript #TypeSafety #ReactDevelopment #JavaScript #SoftwareEngineering
To view or add a comment, sign in
-
-
𝗛𝗼𝘄 𝗚𝗮𝗿𝗯𝗮𝗴𝗲 𝗖𝗼𝗹𝗹𝗲𝗰𝘁𝗶𝗼𝗻 𝗪𝗼𝗿𝗸𝘀 𝗶𝗻 𝗡𝗼𝗱𝗲.𝗷𝘀 As developers, we often focus on writing efficient code—but what about memory management behind the scenes? In 𝗡𝗼𝗱𝗲.𝗷𝘀, garbage collection (GC) is handled automatically by the 𝗩𝟴 𝗝𝗮𝘃𝗮𝗦𝗰𝗿𝗶𝗽𝘁 𝗲𝗻𝗴𝗶𝗻𝗲, so you don’t need to manually free memory like in languages such as C or C++. But understanding how it works can help you write more optimized and scalable applications. 𝗞𝗲𝘆 𝗖𝗼𝗻𝗰𝗲𝗽𝘁𝘀: 𝟭. 𝗠𝗲𝗺𝗼𝗿𝘆 𝗔𝗹𝗹𝗼𝗰𝗮𝘁𝗶𝗼𝗻 Whenever you create variables, objects, or functions, memory is allocated in two main areas: Stack→ Stores primitive values and references Heap→ Stores objects and complex data 𝟮. 𝗚𝗮𝗿𝗯𝗮𝗴𝗲 𝗖𝗼𝗹𝗹𝗲𝗰𝘁𝗶𝗼𝗻 (𝗠𝗮𝗿𝗸-𝗮𝗻𝗱-𝗦𝘄𝗲𝗲𝗽) V8 uses a technique called Mark-and-Sweep: * It starts from “root” objects (global scope) * Marks all reachable objects * Unreachable objects are considered garbage * Then, it sweeps (removes) them from memory 𝟯. 𝗚𝗲𝗻𝗲𝗿𝗮𝘁𝗶𝗼𝗻𝗮𝗹 𝗚𝗮𝗿𝗯𝗮𝗴𝗲 𝗖𝗼𝗹𝗹𝗲𝗰𝘁𝗶𝗼𝗻 Not all objects live the same lifespan: Young Generation (New Space) → Short-lived objects Old Generation (Old Space) → Long-lived objects Objects that survive multiple GC cycles get promoted to the Old Generation. 𝟰. 𝗠𝗶𝗻𝗼𝗿 & 𝗠𝗮𝗷𝗼𝗿 𝗚𝗖 Minor GC (Scavenge)→ Fast cleanup of short-lived objects Major GC (Mark-Sweep / Mark-Compact) → Handles long-lived objects but is more expensive 𝟱. 𝗦𝘁𝗼𝗽-𝘁𝗵𝗲-𝗪𝗼𝗿𝗹𝗱 During GC, execution pauses briefly. Modern V8 minimizes this with optimizations like incremental and concurrent GC. 𝗖𝗼𝗺𝗺𝗼𝗻 𝗠𝗲𝗺𝗼𝗿𝘆 𝗜𝘀𝘀𝘂𝗲𝘀: * Memory leaks due to unused references * Global variables holding data unnecessarily * Closures retaining large objects 𝗕𝗲𝘀𝘁 𝗣𝗿𝗮𝗰𝘁𝗶𝗰𝗲𝘀: * Avoid global variables * Clean up event listeners and timers * Use streams for large data processing * Monitor memory using tools like Chrome DevTools or `--inspect` Understanding GC = Writing better, faster, and scalable applications #NodeJS #JavaScript #BackendDevelopment #V8 #Performance #WebDevelopment
To view or add a comment, sign in
-
-
🚀 From a simple Login Panel to a complete Customer Management System 💻✨ Built this project step by step using HTML, CSS, JavaScript, Flask API & SQL Server 🔥 🔐 Secure Login System ➕ Add Customers 📂 Upload Photos 📋 Load Customer Data 🗑️ Delete Records 📄 View Full Details Every line of code is improving my skills and taking me one step closer to becoming a better developer 💯👨💻 This project helped me understand frontend + backend connection, APIs, database handling, and real-world CRUD operations. Still learning, still building, still growing 🚀 More amazing projects coming soon... Stay connected 💙✨ GitHub:-https://lnkd.in/g5sFhByi #coding #programming #webdevelopment #developer #python #flask #javascript #html #css #sqlserver #database #github #frontend #backend #tech #codingproject 🔥
To view or add a comment, sign in
-
You don’t fix a messy database by just breaking tables. You fix it by understanding why data becomes messy in the first place 👇 Normalisation is a technique. Functional Dependency is the logic behind it. If you skip FD, you’re just guessing your schema. Normalisation ≠ Functional Dependency Normalisation → Organizing tables to reduce redundancy Functional Dependency → Defining how one attribute depends on another When building real systems, you don’t just use Normalisation — you rely on Functional Dependency to handle data consistency and prevent anomalies. Example: UserID → Email If you store Email in multiple places despite this dependency, you’ll face: - update anomalies - deletion issues - inconsistent data ⚠️ Armstrong’s Axioms (Reflexive, Augmentation, Transitivity) are not just theory — they help you reason about how your data should behave. 1NF, 2NF, 3NF, BCNF are results. Functional Dependency is the foundation 🧠 This small distinction changes how you design systems. Building systems > memorizing concepts 🚀 What’s one concept developers often misunderstand? #fullstackdeveloper #softwareengineering #webdevelopment #javascript #reactjs #backend #buildinpublic #nodejs #nextjs #typescript
To view or add a comment, sign in
-
-
TypeScript used naively adds syntax. Used correctly, it prevents entire bug classes. Here are the patterns that actually matter in production. ── Discriminated Unions ── Stop using optional fields for state that has clear phases. Instead of: { data?: User; error?: string; loading?: boolean } Use: → { status: 'loading' } → { status: 'success'; data: User } → { status: 'error'; error: string } TypeScript now narrows correctly in every branch. No more 'data might be undefined' checks scattered everywhere. ── The satisfies Operator (TS 4.9+) ── Validates a value against a type without widening it. You keep autocomplete on specific keys. You get the type safety check. Best of both worlds. ── Template Literal Types ── Generate all valid string combinations at compile time. type ApiCall = `${HTTPMethod} ${Endpoint}` TypeScript tells you when you're calling an endpoint that doesn't exist. ── Branded Types ── Two strings that are semantically different: type UserId = string & { readonly __brand: 'UserId' } type PostId = string & { readonly __brand: 'PostId' } Now you can't accidentally pass a PostId where a UserId is expected. Even though both are just strings at runtime. ── unknown over any ── any disables the type checker entirely. unknown forces you to narrow before using the value. One creates bugs. The other prevents them. TypeScript's real value: Making impossible states unrepresentable at compile time. Not just adding type annotations. #TypeScript #Frontend #JavaScript #SoftwareEngineering #WebDevelopment
To view or add a comment, sign in
-
In this post, I focused on visualizing how data moves within a React application using a Data Flow Diagram (DFD). Understanding data flow allows developers to: • Build more organized and scalable applications • Avoid unnecessary complexity and bugs • Clearly separate logic from UI • Improve maintainability and readability This approach helped me move beyond writing components to truly understanding how data drives the entire application. #React #Frontend #WebDevelopment #JavaScript #SoftwareArchitecture #CleanCode
To view or add a comment, sign in
-
-
I recently wrote about something that looked simple at first, but turned out to be a proper engineering workflow: building bulk search for large datasets in React + Spring Boot. A few lessons stood out for me: 1) Bulk search is not just “submit a big form”. It is a pipeline: normalize, validate, chunk, process, and report. 2) The backend is not the only bottleneck. Large result sets and heavy client-side parsing can hurt the UI too. 3) The feature feels trustworthy only when users can clearly see what was valid, invalid, duplicate, or not found. In the article, I break down: * textarea vs CSV/TXT upload handling * validation strategy across frontend and backend * chunking, scalability, and partial failure reporting * trade-offs I’d keep — and what I’d change next time Read the full article here: https://lnkd.in/gRuSiPnH #React #SpringBoot #Java #FullStack #SoftwareEngineering #WebDevelopment #SystemDesign
To view or add a comment, sign in
-
Most frontend bugs aren’t in your code… They’re in your data flow. . . I used to think bugs came from “wrong logic” or missing edge cases in components. But most of the time, the UI was doing exactly what I told it to do… The problem was what I was feeding into it. Data coming in too early (before it’s ready). State updates are happening in the wrong order. Multiple sources of truth are fighting each other. Props being passed without clear ownership And suddenly… A perfectly written component starts behaving unpredictably. . . What fixed it for me wasn’t rewriting components. It was: → Making data flow predictable → Keeping a single source of truth → Being intentional about when and where state updates. → Separating data logic from UI logic . . Clean components don’t save you If your data flow is messy. Frontend isn’t just about how things look… It’s about how data moves. . . What’s one bug you chased for hours…that turned out to be a data flow issue? . . #frontend #reactjs #webdevelopment #softwareengineering #coding #devlife #developerexperience #javascript
To view or add a comment, sign in
-
-
𝗧𝘆𝗽𝗲𝗦𝗰𝗿𝗶𝗽𝘁 𝗣𝗮𝘁𝘁𝗲𝗿𝗻𝘀 𝗜 𝗔𝗰𝘁𝘂𝗮𝗹𝗹𝘆 𝗨𝘀𝗲 𝗗𝗮𝗶𝗹𝘆 There is a moment with TypeScript when you stop fighting it. For me it was 2 AM on a Tuesday. A production bug that would have been impossible with good types. That changed how I think about code. This is not a beginner guide. If you are still confused about interface vs type, read something else. This is what is in my head when I code today. The patterns I use without thinking. The ones that saved me. The mistakes I made before I understood them. If I had to keep one pattern it would be this. Discriminated unions. You create a union type. Each variant has a common property like `status` or `kind`. TypeScript uses this to know exactly what you are working with. type ApiResponse<T> = | { status: 'loading' } | { status: 'error'; error: string; code: number } | { status: 'success'; data: T; timestamp: Date }; function renderUser(response: ApiResponse<User>) { switch (response.status) { case 'loading': return <Spinner />; case 'error': // TypeScript knows response.error and response.code exist here return <ErrorMessage message={response.error} code={response.code} />; case 'success': // TypeScript knows response.data and response.timestamp exist here return <UserCard user={response.data} />; } } TypeScript forces you to handle every case. Add a new state like `cancelled`. The compiler tells you exactly where you forgot to handle it. It is like a silent pair programmer. I use this for: - Domain events - UI states - Async operation results Last year I built an e-commerce system. I modeled every order state this way. type OrderState = | { kind: 'draft'; items: CartItem[] } | { kind: 'pending_payment'; orderId: string; total: Money } | { kind: 'paid'; orderId: string; paymentId: string; paidAt: Date } | { kind: 'shipped'; orderId: string; trackingCode: string } | { kind: 'delivered'; orderId: string; deliveredAt: Date } | { kind: 'cancelled'; orderId: string; reason: string }; Each state has only the data it needs. No weird optional fields. No `trackingCode: string | null` where you do not know if null means not shipped or an old order. The type is the documentation. Branded types This one was harder to learn but I cannot live without it. The problem is simple. `userId: string` and `productId: string` are the same type to TypeScript. They are not the same to your business. Mixing them is a bug. Without branded types TypeScript does not catch this error. function getUser(id: string) { /* ... */ } function getProduct(id: string) { /* ... */ } const productId = '123'; getUser(productId); // TypeScript says this is fine. It is wrong. With branded types you create unique types from primitives. type Brand<T, B> = T & { readonly __brand: B }; type UserId = Brand<string, 'UserId'>; type ProductId = Brand<stri
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development