Is it necessary to manually validate parameters in TypeScript when developing a library?

Understanding the basic workings of TypeScript, it's clear that TypeScript transpiles code to JavaScript without adding extra behavior like type checking during execution. For instance,

function example(parameter: string): void {
  console.log(parameter.charAt(1));
}

will be transpiled to:

"use strict";
function example(parameter) {
  console.log(parameter.charAt(1));
}

If a JavaScript user calls example(3), an error

Uncaught TypeError: parameter.charAt is not a function
will be thrown.

Why am I asking this question? Because I'm planning to spend a lot of time improving my library (@yamato-daiwa/es-extensions) and significantly increasing its size. Let's look at the addElementsToArray function from version 1.6.x:

export default function addElementsToArray<ArrayElement>(
  namedParameters:
    {
      targetArray: Array<ArrayElement>;
      newElements: Array<ArrayElement>;
      mutably: boolean;
    } &
    (
      { toStart: true; } |
      { toEnd: true; } |
      { toPosition__numerationFrom0: number; } |
      { toPosition__numerationFrom1: number; }
    )
): Array<ArrayElement> {

  const workpiece: Array<ArrayElement> = namedParameters.mutably ?
      namedParameters.targetArray : [ ...namedParameters.targetArray ];

  // more functionality...
}

With added type checking, the function now looks like this:

// import statements...

export default function addElementsToArray<ArrayElement>(
  namedParameters:
      Readonly<
        (
          {
            mutably: true;
            targetArray: Array<ArrayElement>;
          } |
          {
            mutably: false;
            targetArray: ReadonlyArray<ArrayElement>;
          }
        ) &
        {
          newElements: ReadonlyArray<ArrayElement>;
          toStart?: true;
          toEnd?: true;
          toPosition__numerationFrom0?: number;
          toPosition__numerationFrom1?: number;
        }
      >
): Array<ArrayElement> {

  // validation process...

  // more functionality...
}

The validations have increased the function size and dependencies, making the distributable heavier. This can be crucial for front-end applications where every kilobyte matters.

In addition to these checks, we could:

  • Determine which alternatively required parameters were passed when multiple were specified.
  • Separate the checks for parameter types and presence.
  • Log errors for incorrect subtypes of certain parameters.

Potential Issues

Non-TypeScript users may encounter bugs due to invalid parameter types, causing wasted time on investigations. Getting senior web developers' opinions on whether the increase in library size due to parameter validation is justified is important to me.

Bounty Update

This question has been answered, but I seek advice on whether increasing library size for parameter validation is acceptable or should be avoided to maintain a slim library. Input from experienced developers is appreciated.

Answer №1

Validating input at the interface where customers interact with your system is a sound and widely adopted practice.

The initial validation code may seem redundant, but it actually serves to simplify and strengthen the core functionality of these functions.

To streamline the code further, consider utilizing an existing assertion library or creating one tailored to your specific needs.

Answer №2

It seems like there might be a bit of confusion between two separate issues at play here. On one hand, we have the typing of interfaces that users interact with (such as function signatures), which allows TypeScript to ensure that function calls are made with the correct values and is essential for compatibility with TypeScript projects. On the other hand, there's the validation of interfaces, where we programmatically check each input to ensure it meets the right type and value requirements.

One major benefit of using TypeScript is that these programmatic checks are often not needed.

I would advise against attempting to validate every single input like in your example. It's nearly impossible to block every invalid value, and in scenarios where efficiency is crucial, unnecessary checks should be avoided. Many users of this module will likely validate their data before passing it to your code, especially with user inputs.

Additionally, lengthy and complicated code is harder to maintain and can slow down the addition of new features. This complexity also increases the likelihood of introducing bugs. While there are certain cases where preventing invalid values is critical, focusing on adding checks specifically in those areas is a better practice. If someone provides incorrect arguments to a list manipulation function and encounters an error, it's not a catastrophic event.

Instead of investing time in extensive validation, consider creating comprehensive documentation for JavaScript users of your module. Not only does this benefit JavaScript users, but it also assists TypeScript users in understanding how to effectively utilize your code.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the most effective method for identifying duplicate values in a multidimensional array using typescript or javascript?

I have a 2D array as shown below: array = [ [ 1, 1 ], [ 1, 2 ], [ 1, 1 ], [ 2, 3 ] ] I am looking to compare the values in the array indexes to check for duplicates. For example array[0] = [1,1]; array[1] = [1,2]; array[2] = [1,1]; We can see that ...

Achieving intellisense functionality in TypeScript without the use of classes

Just dipped my toes into TypeScript, attempting to convert this basic JavaScript code to TypeScript. Here is the JavaScript code snippet: Item = {} Item.buy = function (id) {} Item.sell = function (id) {} I prefer not to use classes and would like to ut ...

Utilizing *ngIf for Showing Elements Once Data is Completely Loaded

While working on my Angular 2 app, I encountered an issue with the pagination UI loading before the data arrives. This causes a visual glitch where the pagination components initially appear at the top of the page and then shift to the bottom once the data ...

Challenging Issue: "The 'any' type cannot be assigned to the 'never' type"

Currently facing a challenging Typescript problem that has me puzzled. The issue arises at the line themeToChange[tileId][key] = value; The error message states Type 'any' is not assignable to type 'never' This error is directly rela ...

At what point does the constructor of an injected service in Angular execute?

When using @Injectable({providedIn: 'root'}) in Angular 7 for a service, the constructor of the service executes when exactly? Is it upon the creation of a component that utilizes it as a dependency or does it wait until a method within the servi ...

Troubleshooting Issue with Angular Library: Live Reload Feature Not Functioning

In setting up my Angular workspace, I have 3 libraries and one application (with more to be added in the future). This is how the TypeScript paths are configured: "paths": { "@lib/a/*": [ "projects/libs/a/*", ...

Angular, manipulating components through class references instead of creating or destroying them

I am exploring ways to move an angular component, and I understand that it can be achieved through construction and destruction. For example, you can refer to this link: https://stackblitz.com/edit/angular-t3rxb3?file=src%2Fapp%2Fapp.component.html Howeve ...

Exploring the benefits of leveraging TypeScript with AWS NodeJS for improved stacktrace visibility over traditional JavaScript

I'm contemplating the idea of transitioning my existing JavaScript codebase to incorporate TypeScript in NodeJS. One aspect that I am concerned about is being able to view the stack trace in AWS CloudWatch (request log) in case an error occurs during ...

Ways to dynamically link a JSON response object to an entity?

In my ng2 implementation, I have a user.service.ts file that calls a REST service and returns JSON data. The code snippet below shows how the getUser function retrieves the user information: getUser(id: number): Promise<User> { return this.http. ...

Looking to retrieve HTML elements based on their inner text with queryselectors?

I am looking to extract all the HTML divs that contain specific HTML elements with innerText = ' * ' and save them in an array using Typescript. If I come across a span element with the innerText= ' * ', I want to add the parent div to ...

The function signature '() => Element' is incompatible with the type 'string'

Greetings! I have a standard function that returns a span with a prop (if I'm not mistaken). In my TS code, I am encountering this error: Error image Below is the code from the file named qCard.tsx: import { QuestionAnswerTwoTone } from "@material- ...

Intellisense missing in VSCode for Angular and typings

Attempting to start a new project using Angular 1.5.5 and looking to incorporate TypeScript into my coding process within Visual Studio Code. I have included the necessary typings for Angular in my project: typings install angular --save --ambient I&ap ...

The HTML file that was typically generated by Webpack is now missing from the output

While working on my nodejs app using typescript, react, and webpack, everything was running smoothly. I was getting the expected output - an HTML file along with the bundle file. However, out of nowhere and without making any changes to my code, I noticed ...

When using React and Material UI, there seems to be an issue with the Popover component where calling `setAnchorEl(null)` on the onClose event does not properly

I am encountering an issue with a Popover (imported from MaterialUI) nested inside a MenuItem (also imported from MaterialUI). The open prop for the popover is set to the boolean value of anchorEl. The onClose function is supposed to handle setting anchorE ...

During the transpiling process, the metadata of an Angular component may become lost

Encountering another error: Uncaught Error: Unexpected value 'UserDialogComponent' declared by the module 'AppModule'. Please add a @Pipe/@Directive/@Component annotation. Current behavior Summary: When incorporating an external libra ...

Can you specify the necessary import statement for CallableContext?

My Google Cloud function is simple and looks like this: import * as functions from 'firebase-functions'; var util = require('util') export const repeat = functions.https.onCall( function (data, context) { console.log(&apo ...

Master the Art of Scrolling Lists in Ionic 2

I am currently using Ionic2 for my project. One of the challenges I'm facing is scrolling to the top of a list when a specific event, called messageSend, occurs. Let me show you the code for this: <ion-content padding class="messages-page-conten ...

Converting SASS in real-time using SystemJS

I have been reading various blogs discussing the use of SystemJS and SASS transpiling, but most of the examples I come across involve pre-processing SASS files before importing them into JavaScript code. However, I am interested in being able to directly i ...

Sort through a list of objects by certain properties

I'm currently dealing with two arrays: one contains displayed columns and the other contains objects retrieved from a database, with more attributes than the displayed columns. displayedColumns = ['CompanyName','Ticker', 'Id& ...

What could be causing the elements in my array to appear as undefined?

https://i.stack.imgur.com/ze1tx.png I'm stuck trying to understand why I can't extract data from the array. const usedPlatformLog: Date[] = [] users.forEach(el => { usedPlatformLog.push(el.lastUsed) }) console.log(usedPlatformLog) // disp ...