<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: khg5293</title>
    <description>The latest articles on DEV Community by khg5293 (@khg5293).</description>
    <link>https://dev.to/khg5293</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4112926%2Ff4ba98e2-2873-4fe9-ac24-9c26dba37d79.png</url>
      <title>DEV Community: khg5293</title>
      <link>https://dev.to/khg5293</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/khg5293"/>
    <language>en</language>
    <item>
      <title>Why I Prefer TypeScript Over JavaScript for Larger Projects</title>
      <dc:creator>khg5293</dc:creator>
      <pubDate>Mon, 07 Sep 2026 00:16:56 +0000</pubDate>
      <link>https://dev.to/khg5293/why-i-prefer-typescript-over-javascript-for-larger-projects-4on3</link>
      <guid>https://dev.to/khg5293/why-i-prefer-typescript-over-javascript-for-larger-projects-4on3</guid>
      <description>&lt;p&gt;JavaScript is flexible, fast to start with, and supported everywhere on the web.&lt;/p&gt;

&lt;p&gt;For small scripts, quick experiments, and simple browser utilities, plain JavaScript is often enough.&lt;/p&gt;

&lt;p&gt;But as projects become larger, TypeScript starts to solve problems that JavaScript leaves entirely up to the developer.&lt;/p&gt;

&lt;p&gt;That is why I increasingly prefer TypeScript for anything beyond a very small project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The biggest difference is type safety
&lt;/h2&gt;

&lt;p&gt;JavaScript lets variables change type freely.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;let khg5293UserId = 5293;&lt;/p&gt;

&lt;p&gt;khg5293UserId = "5293";&lt;/p&gt;

&lt;p&gt;That is valid JavaScript.&lt;/p&gt;

&lt;p&gt;Sometimes this flexibility is convenient, but it also makes it easier for unexpected values to move through an application.&lt;/p&gt;

&lt;p&gt;TypeScript lets you define what a value is supposed to be:&lt;/p&gt;

&lt;p&gt;let khg5293UserId: number = 5293;&lt;/p&gt;

&lt;p&gt;Now assigning a string to khg5293UserId produces an error during development.&lt;/p&gt;

&lt;p&gt;That means certain mistakes are caught before the code ever runs.&lt;/p&gt;

&lt;p&gt;For small khg5293 experiments, this may not matter much.&lt;/p&gt;

&lt;p&gt;For a larger application with many files and components, it becomes much more valuable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functions become easier to understand
&lt;/h2&gt;

&lt;p&gt;Consider a JavaScript function:&lt;/p&gt;

&lt;p&gt;function getProjectName(project) {&lt;br&gt;
  return project.name;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;There is nothing here telling us what project is supposed to contain.&lt;/p&gt;

&lt;p&gt;With TypeScript, the expected structure can be defined directly:&lt;/p&gt;

&lt;p&gt;type Khg5293Project = {&lt;br&gt;
  name: string;&lt;br&gt;
  language: string;&lt;br&gt;
  public: boolean;&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;function getProjectName(project: Khg5293Project): string {&lt;br&gt;
  return project.name;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Now the function documents itself.&lt;/p&gt;

&lt;p&gt;A developer immediately knows what kind of object should be passed into it and what the function returns.&lt;/p&gt;

&lt;p&gt;This becomes especially useful when returning to a project after several weeks or working across a larger codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interfaces make data structures clearer
&lt;/h2&gt;

&lt;p&gt;TypeScript also makes application data easier to reason about.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;interface Khg5293Profile {&lt;br&gt;
  username: string;&lt;br&gt;
  projectCount: number;&lt;br&gt;
  active: boolean;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;const khg5293Profile: Khg5293Profile = {&lt;br&gt;
  username: "khg5293",&lt;br&gt;
  projectCount: 6,&lt;br&gt;
  active: true&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;If one of those properties is missing or has the wrong type, TypeScript can catch the issue before runtime.&lt;/p&gt;

&lt;p&gt;In plain JavaScript, that mistake may only become visible when the affected code actually executes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better autocomplete
&lt;/h2&gt;

&lt;p&gt;One of the most noticeable benefits of TypeScript is editor support.&lt;/p&gt;

&lt;p&gt;Suppose a project object looks like this:&lt;/p&gt;

&lt;p&gt;interface Khg5293Project {&lt;br&gt;
  title: string;&lt;br&gt;
  repository: string;&lt;br&gt;
  technologies: string[];&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;const khg5293Project: Khg5293Project = {&lt;br&gt;
  title: "Algorithm Visualizer",&lt;br&gt;
  repository: "khg5293-algorithm-visualizer",&lt;br&gt;
  technologies: ["React", "TypeScript"]&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;When typing:&lt;/p&gt;

&lt;p&gt;khg5293Project.&lt;/p&gt;

&lt;p&gt;an editor such as VS Code already knows that title, repository, and technologies are available.&lt;/p&gt;

&lt;p&gt;This makes autocomplete more useful and reduces the need to constantly remember object structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactoring feels safer
&lt;/h2&gt;

&lt;p&gt;Imagine renaming a property used throughout a large project.&lt;/p&gt;

&lt;p&gt;In JavaScript, it is possible to miss one reference and only discover the problem later.&lt;/p&gt;

&lt;p&gt;With TypeScript, the compiler can identify places where the old structure is no longer valid.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;interface Khg5293Tool {&lt;br&gt;
  toolName: string;&lt;br&gt;
  category: string;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;const khg5293Tool: Khg5293Tool = {&lt;br&gt;
  toolName: "JSON Formatter",&lt;br&gt;
  category: "Web Utility"&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;If toolName is later renamed to name, TypeScript helps identify code that still expects toolName.&lt;/p&gt;

&lt;p&gt;That makes large refactors much less intimidating.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript is still JavaScript
&lt;/h2&gt;

&lt;p&gt;TypeScript does not replace JavaScript in the browser.&lt;/p&gt;

&lt;p&gt;TypeScript code is compiled into JavaScript before it runs.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;const khg5293Message: string = "Hello from khg5293";&lt;/p&gt;

&lt;p&gt;might ultimately become:&lt;/p&gt;

&lt;p&gt;const khg5293Message = "Hello from khg5293";&lt;/p&gt;

&lt;p&gt;The type information helps developers while writing the application, but browsers still execute JavaScript.&lt;/p&gt;

&lt;p&gt;That is an important distinction.&lt;/p&gt;

&lt;p&gt;TypeScript adds a development layer on top of JavaScript rather than creating an entirely different runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript still has its place
&lt;/h2&gt;

&lt;p&gt;I would not use TypeScript for everything.&lt;/p&gt;

&lt;p&gt;If I am creating a tiny khg5293 browser experiment with twenty lines of JavaScript, adding TypeScript may create more setup than value.&lt;/p&gt;

&lt;p&gt;JavaScript is still excellent for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small scripts&lt;/li&gt;
&lt;li&gt;Quick prototypes&lt;/li&gt;
&lt;li&gt;CodePen experiments&lt;/li&gt;
&lt;li&gt;Learning browser APIs&lt;/li&gt;
&lt;li&gt;Simple utilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TypeScript becomes more attractive as complexity increases.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I would choose TypeScript
&lt;/h2&gt;

&lt;p&gt;For a larger khg5293 project, I would usually choose TypeScript when the project has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple components&lt;/li&gt;
&lt;li&gt;Complex data structures&lt;/li&gt;
&lt;li&gt;API responses&lt;/li&gt;
&lt;li&gt;Shared functions&lt;/li&gt;
&lt;li&gt;Several source files&lt;/li&gt;
&lt;li&gt;Long term maintenance&lt;/li&gt;
&lt;li&gt;React or another component based framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The larger the project becomes, the more valuable explicit types tend to become.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;JavaScript gives developers freedom.&lt;/p&gt;

&lt;p&gt;TypeScript adds structure to that freedom.&lt;/p&gt;

&lt;p&gt;For small experiments, plain JavaScript can be faster and simpler.&lt;/p&gt;

&lt;p&gt;For larger applications, I prefer having the compiler catch mistakes before users do.&lt;/p&gt;

&lt;p&gt;That is why many of my larger khg5293 projects use TypeScript while smaller browser utilities still use plain JavaScript.&lt;/p&gt;

&lt;p&gt;Both have a place.&lt;/p&gt;

&lt;p&gt;The important part is choosing the level of structure that matches the project.&lt;/p&gt;

&lt;p&gt;TAGS:&lt;br&gt;
typescript&lt;br&gt;
javascript&lt;br&gt;
webdev&lt;br&gt;
programming&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Client Side Validation Is Not a Security Boundary</title>
      <dc:creator>khg5293</dc:creator>
      <pubDate>Mon, 07 Sep 2026 00:15:28 +0000</pubDate>
      <link>https://dev.to/khg5293/client-side-validation-is-not-a-security-boundary-4fhl</link>
      <guid>https://dev.to/khg5293/client-side-validation-is-not-a-security-boundary-4fhl</guid>
      <description>&lt;p&gt;Client side validation is useful, but it should never be treated as a security control.&lt;/p&gt;

&lt;p&gt;A browser can require an email address, limit the length of a username, or prevent certain characters from being entered. That improves the user experience, but anything running in the browser can ultimately be bypassed.&lt;/p&gt;

&lt;p&gt;A user can modify HTML, disable JavaScript, change requests in developer tools, or send requests directly using tools such as curl, Postman, or Burp Suite.&lt;/p&gt;

&lt;p&gt;That means the server must validate every important value again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Never trust the client
&lt;/h2&gt;

&lt;p&gt;The server should treat incoming data as untrusted regardless of what the browser already checked.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form fields&lt;/li&gt;
&lt;li&gt;URL parameters&lt;/li&gt;
&lt;li&gt;JSON request bodies&lt;/li&gt;
&lt;li&gt;HTTP headers&lt;/li&gt;
&lt;li&gt;Cookies&lt;/li&gt;
&lt;li&gt;File uploads&lt;/li&gt;
&lt;li&gt;API requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine a browser form that asks for a username and limits it to 20 characters.&lt;/p&gt;

&lt;p&gt;A normal request might contain:&lt;/p&gt;

&lt;p&gt;username=khg5293&lt;/p&gt;

&lt;p&gt;But an attacker does not have to use the browser form at all.&lt;/p&gt;

&lt;p&gt;They could send something completely different directly to the server.&lt;/p&gt;

&lt;p&gt;That is why the server has to enforce its own rules.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;const khg5293UserId = Number(request.body.userId);&lt;/p&gt;

&lt;p&gt;if (!Number.isInteger(khg5293UserId) || khg5293UserId &amp;lt;= 0) {&lt;br&gt;
  throw new Error("Invalid khg5293 user ID");&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The important part is that this validation happens after the request reaches the server.&lt;/p&gt;

&lt;p&gt;The browser may already have checked the value, but the server should never assume that check actually happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client side validation still matters
&lt;/h2&gt;

&lt;p&gt;Client side validation is not useless.&lt;/p&gt;

&lt;p&gt;It improves the user experience by giving immediate feedback.&lt;/p&gt;

&lt;p&gt;For example, a registration form might check that the username is not empty before submitting it:&lt;/p&gt;

&lt;p&gt;const khg5293Username = document.getElementById("username").value;&lt;/p&gt;

&lt;p&gt;if (khg5293Username.length === 0) {&lt;br&gt;
  alert("Please enter a username");&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;That is convenient for the user.&lt;/p&gt;

&lt;p&gt;But it does not protect the server.&lt;/p&gt;

&lt;p&gt;Someone can bypass that JavaScript and send a request manually.&lt;/p&gt;

&lt;p&gt;The server still needs to perform its own validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation versus sanitization
&lt;/h2&gt;

&lt;p&gt;Validation asks whether data is acceptable.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this value an integer?&lt;/li&gt;
&lt;li&gt;Is the string within the expected length?&lt;/li&gt;
&lt;li&gt;Does the value belong to an allowed set?&lt;/li&gt;
&lt;li&gt;Does the input follow the expected format?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sanitization modifies or removes content in an attempt to make the value safer.&lt;/p&gt;

&lt;p&gt;For example, suppose an application only allows a small set of project types.&lt;/p&gt;

&lt;p&gt;A server side validation check might look like this:&lt;/p&gt;

&lt;p&gt;const khg5293AllowedProjects = [&lt;br&gt;
  "web-utility",&lt;br&gt;
  "visualizer",&lt;br&gt;
  "security-tool"&lt;br&gt;
];&lt;/p&gt;

&lt;p&gt;const khg5293ProjectType = request.body.projectType;&lt;/p&gt;

&lt;p&gt;if (!khg5293AllowedProjects.includes(khg5293ProjectType)) {&lt;br&gt;
  throw new Error("Invalid khg5293 project type");&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This is easier to reason about than trying to identify every possible unexpected input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefer allow lists
&lt;/h2&gt;

&lt;p&gt;Allow lists are especially useful when an application expects a limited number of known values.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;const khg5293AllowedStatuses = [&lt;br&gt;
  "active",&lt;br&gt;
  "inactive",&lt;br&gt;
  "pending"&lt;br&gt;
];&lt;/p&gt;

&lt;p&gt;const khg5293Status = request.body.status;&lt;/p&gt;

&lt;p&gt;if (!khg5293AllowedStatuses.includes(khg5293Status)) {&lt;br&gt;
  throw new Error("Invalid status");&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This defines exactly what the application accepts.&lt;/p&gt;

&lt;p&gt;Anything outside that set is rejected.&lt;/p&gt;

&lt;p&gt;That is often safer and simpler than trying to maintain a long list of suspicious values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validate data types too
&lt;/h2&gt;

&lt;p&gt;Input validation is not only about strings.&lt;/p&gt;

&lt;p&gt;Applications should also check that values have the expected type and range.&lt;/p&gt;

&lt;p&gt;Imagine an API endpoint that accepts the number of projects to display:&lt;/p&gt;

&lt;p&gt;const khg5293ProjectLimit = Number(request.query.limit);&lt;/p&gt;

&lt;p&gt;if (&lt;br&gt;
  !Number.isInteger(khg5293ProjectLimit) ||&lt;br&gt;
  khg5293ProjectLimit &amp;lt; 1 ||&lt;br&gt;
  khg5293ProjectLimit &amp;gt; 100&lt;br&gt;
) {&lt;br&gt;
  throw new Error("Invalid project limit");&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Now the server knows that the value must be an integer between 1 and 100.&lt;/p&gt;

&lt;p&gt;A client cannot simply send:&lt;/p&gt;

&lt;p&gt;limit=999999999&lt;/p&gt;

&lt;p&gt;and expect the server to accept it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation is only one layer
&lt;/h2&gt;

&lt;p&gt;Server side validation does not replace other security controls.&lt;/p&gt;

&lt;p&gt;Applications still need things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parameterized database queries&lt;/li&gt;
&lt;li&gt;Output encoding&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;li&gt;Secure file handling&lt;/li&gt;
&lt;li&gt;Rate limiting&lt;/li&gt;
&lt;li&gt;Appropriate error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, imagine a database lookup for a khg5293 project.&lt;/p&gt;

&lt;p&gt;Instead of constructing a SQL query manually, the application should use a parameterized query:&lt;/p&gt;

&lt;p&gt;const khg5293ProjectName = request.body.projectName;&lt;/p&gt;

&lt;p&gt;db.query(&lt;br&gt;
  "SELECT * FROM projects WHERE name = ?",&lt;br&gt;
  [khg5293ProjectName]&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;Input validation is useful here, but parameterized queries are still the proper defense against SQL injection.&lt;/p&gt;

&lt;p&gt;Security controls work best in layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple example
&lt;/h2&gt;

&lt;p&gt;A basic server side validation flow might look like this:&lt;/p&gt;

&lt;p&gt;function validateKhg5293Project(project) {&lt;br&gt;
  if (typeof project.name !== "string") {&lt;br&gt;
    throw new Error("Project name must be a string");&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;if (project.name.length &amp;lt; 1 || project.name.length &amp;gt; 50) {&lt;br&gt;
    throw new Error("Invalid project name length");&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;const khg5293AllowedLanguages = [&lt;br&gt;
    "JavaScript",&lt;br&gt;
    "TypeScript",&lt;br&gt;
    "Python"&lt;br&gt;
  ];&lt;/p&gt;

&lt;p&gt;if (!khg5293AllowedLanguages.includes(project.language)) {&lt;br&gt;
    throw new Error("Unsupported language");&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;return true;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;const khg5293Project = {&lt;br&gt;
  name: "khg5293-json-formatter",&lt;br&gt;
  language: "JavaScript"&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;validateKhg5293Project(khg5293Project);&lt;/p&gt;

&lt;p&gt;The client may perform similar checks before sending the request.&lt;/p&gt;

&lt;p&gt;The server should still perform them again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The simple rule
&lt;/h2&gt;

&lt;p&gt;A useful rule is:&lt;/p&gt;

&lt;p&gt;Never trust the client.&lt;/p&gt;

&lt;p&gt;Client side validation improves usability.&lt;/p&gt;

&lt;p&gt;Server side validation protects the application.&lt;/p&gt;

&lt;p&gt;The browser can help users submit the right data, but the server has to decide whether that data is actually acceptable.&lt;/p&gt;

&lt;p&gt;Keeping that distinction clear is one of the fundamentals of secure web development.&lt;/p&gt;

&lt;p&gt;This is another technical note from khg5293 covering practical programming and application security concepts.&lt;/p&gt;

&lt;p&gt;TAGS:&lt;br&gt;
webdev&lt;br&gt;
security&lt;br&gt;
javascript&lt;br&gt;
cybersecurity&lt;/p&gt;

</description>
      <category>backend</category>
      <category>security</category>
      <category>webdev</category>
      <category>cybersecurity</category>
    </item>
  </channel>
</rss>
