"Utilize Typescript to dynamically check data types during runtime and receive alerts for any potential

INTRODUCTION

I am currently working with Angular 6.

In Angular, typescript is utilized to allow you to specify the data type of your function's arguments:

public fun1(aaa: number) {
  console.log(aaa);
}

If I attempt to call fun1 with a parameter of a different type, an error will be thrown:

public fun2() {
  this.fun1([1, 2, 3]); // TS2345: Argument of type 'number[]' is not assignable to parameter of type 'number'
}

THE PROBLEM

Type checking works effectively when I have control over the arguments in my code files.

However, there are situations where fun1 may be called with parameters retrieved from a backend source.

Since Typescript does not perform runtime checking, no errors would be shown and the code within fun1 would execute with the unexpected input like [1, 2, 3].

-- edited --

The issue isn't just limited to backend responses. In some cases, a library might alter the data type without your knowledge. For example, when using Reactive Forms with a control that should contain a number, it could inadvertently convert the value to a string during editing.

QUESTION

Is there a standard method for implementing type checking at runtime?

I've considered something along these lines:

public fun1(aaa: number) {
  if (typeof aaa !== 'number') {
    console.warn('wrong type');
  } else {
    console.log(aaa);
  }
}

, but WebStorm alerts me that

typeof check is always false: 'aaa' always has type 'number'
.

Including such checks at the beginning of every function seems cumbersome and unnecessary. Does anyone have a more efficient solution for this dilemma?

Answer №1

TypeScript was intentionally designed without providing runtime type information (refer to https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals, Non-goals, point 5).

When TypeScript interacts with external data sources, such as data attributes in HTML or data fetched from a REST API, it cannot determine the data type by itself. However, there are workarounds available. Let's explore two possible solutions.

One way is to bypass the type system using the `as` operator. While not completely type-safe (creating a hole in the type system), this approach aligns partially with TypeScript's objectives (referencing the link above).

For instance, if a function call like `fetchApiSync` returns a simple JavaScript object `{name: "John", age: 42}`, and we have a function:

function introduceMe(person: Person) {
    return `My name is ${person.name} and I'm ${person.age} years old.`
}

along with an interface

interface Person {
    name: string;
    age: number;
}

We can do the following:

const person: Person = fetchPersonFromApi(1);
.

It is ideal for `fetchPersonFromApi` to return a value that matches the `Person` interface so that we can further process it:

const introduction = introduceMe(person);

To achieve this, we might perform something like this:

function fetchPersonFromApi(id: number): Person {
   // synchronous call without error handling for simplicity
   const response: Person = fetchApiSync(`/persons/${id}`) as Person

   return response;
}

This code snippet includes an explicit cast of the API response to a `Person`, ensuring type checking. However, issues may arise if a different data type is returned instead of `Person`. Is there a solution to this problem?

Alternatively, one can utilize `any` (or `unknown` from TS 3) types, allowing skipping of strict type checks where a value of type `any` can be assigned to any other type, including `Person`. Yet, errors may become challenging to debug within the type system. Thus, caution is advised when using these types!

Another viable option is leveraging the `io-ts` library (https://github.com/gcanti/io-ts). This library enables the specification of `runtime types` and conducting runtime type validations, adding an overhead to ensure values match expected types. While introducing additional complexity, io-ts promotes increased type safety and discourages resorting to `any` or `unknown` types. It facilitates deriving pure TypeScript types from io-ts definitions, safeguarding the codebase against reckless type conversions. However, mastering io-ts entails embracing and managing its inherent complexities effectively.

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

Operator in RxJS that maps the elements within an array composed of multiple arrays

disclaimer: I have a creative solution and would like to share it here. While exploring the RxJS documentation for map methods that meet this specific requirement - let's call it mapArray - I haven't been able to find one. of([1, 2, 3]).pipe( ...

Angular developers may encounter a dependency conflict while attempting to install ngx-cookie

I'm currently facing an issue while attempting to add the ngx-cookie package for utilizing the CookieService in my application. Unfortunately, I am encountering some dependency conflicts that look like the following: $ npm install ngx-cookie --save np ...

Using Angular 2 to Showcase JSON Array Data with Component Selector

I am struggling to showcase a specific array value, taxes, using the component selector without any success. At the moment, the component selector is displaying all values in the template/model. My goal is to only display the taxes value of the model. use ...

How can I exhibit JSON object information in an Angular 2 dropdown menu?

CSS <!-- Custom CSS Styling for Dropdown --> <div class="row no-overflow"> <div class="col-md-1 window-pad-height no-overflow"> <m ...

Displaying Firebase data using Angularfire2 5.0 on an Ionic template

Hey everyone, I've been encountering a problem while trying to use angularfire2 v 5.0. I was comfortable using v 4.0 before, but now that I'm transitioning to v 5.0, I'm facing some issues. Does anyone know how I can display real-time data ...

Is Drizzle ORM able to handle decimal values in MySQL as strings?

The data structure: export const myTable = mysqlTable( "MyTable", { id: varchar("id", { length: 191 }).notNull(), value: decimal("value", { precision: 7, scale: 4 }).notNull(), createdAt: datetime("created ...

React - Incorrect use of hooks and class components

Understanding hooks as the opposite of a class component can be confusing. A simple line of code can trigger an error when trying to adapt it for use in a class component. Take, for example, this situation: .jsx files and functional components work seamles ...

Redirecting to different paths using Angular 6 routing

My experience with Angular is fresh, as I embark on crafting my initial Angular application tailored for an admin dashboard. The task at hand involves setting up two distinct layouts: Authentication layout (incorporating login, logout, forgot-password f ...

Create a visual representation of an item within a framework using an Angular directive

I am interested in using a directive to draw a triangle above a series of div elements. In my scenario, I have four squares and two values: charge and normal. The value of charge determines the color of the squares, while normal is used for drawing the t ...

When executing `npm run e2e`, the terminal does not display any output

After building my application with Angular 7, here is a snippet from my package.json file: "scripts": { "ng": "ng", "standardize": "prettier **/*.ts --write", "start": "npm run standardize && ng serve --port 5000", "build": "npm run standa ...

Is there a way to prevent QtLinguist from opening every time Visual Studio tries to display a TypeScript file?

Ever since I installed Qt tools for Visual Studio, my Ctrl+click on a class name triggers Qt Linguist: https://i.stack.imgur.com/USAH1.png This hinders me from checking type definitions, even though Visual Studio has already parsed them. The type informa ...

What are the steps to troubleshoot a Node Package Manager library in Visual Studio Code?

I have created a Typescript library that I plan to use in various NodeJS projects. The source code is included in the NPM package, so when I install it in my projects, the source also gets added to the node_modules folder. Now, during debugging, I want to ...

When a parameter is passed into a React-Query function with an undefined value, it can lead to the API returning a 404 error

Two parameters are sent from the frontend to trigger a GET request in another TypeScript file. It seems that one of the parameters is not successfully passed due to unknown rerenders, resulting in a 404 Error being returned by the API call in the console. ...

Create a TypeScript interface that represents an object type

I have a Data Structure, and I am looking to create an interface for it. This is how it looks: const TransitReport: { title: string; client: string; data: { overdueReviews: number; outstandingCovenantBreaches ...

Discovering the origins of the node.js native modules and delving into the intricacies of typed modules

I am using a Windows machine and trying to locate where node fetches the source code for native modules. On my system, I can only find the @types file which contains "Typed Only" modules. For example, the module "assert" is available in the master/lib fold ...

The element is implicitly assigned an 'any' type as the expression of type 'any' cannot be used to index a type with createStyles

My stylesheet looks like this: const badgeStyle = createStyles({ badge: { borderRadius: "12px", padding: "5px 12px", textTransform: "uppercase", fontSize: "10px", fontWeight: 700, lineHeight ...

Similar to TypeScript's `hasOwnProperty` counterpart

When working with TypeScript objects, is there a way to loop through a dictionary and set properties of another dictionary similar to how it is done in JavaScript? for (let key in dict) { if (obj.hasOwnProperty(key)) { obj[key] = dict[key]; } } If ...

Determine the character count of the text within an *ngFor loop

I am a beginner in Angular (8) and I am trying to determine the length of the input value that I have created using a *ngFor loop as shown below: <div *ngFor="let panel of panels; index as i" class="panel" [id]="'panel-' + panel.id"> & ...

Is it possible to leverage TypeScript type support in Electron by incorporating require statements within functions or conditions?

The Electron Performance documentation advises against loading and running code too soon. It suggests using the strategy of deferring the loading of sizable modules until they are actually needed, rather than placing all require() statements at the top of ...

Utilizing electron as a development dependency in an Ubuntu environment

After installing electron on Ubuntu 17.10, this is the process I followed: ole@mki:~/angular-electron$ npm i --save-dev electron > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d9bcb5bcbaadabb6b799e8f7eef7e8eb"> ...