Typescript's type mismatch does not result in a compile time error

Within my code, I have a function with the following definition:

export async function removeUser(deleteUserId: Types.ObjectId)

There was an instance where I mistakenly called this function and passed a Mongoose object's id parameter, which is a string. This led to a runtime exception later in the code when I attempted to utilize the .equals() method that is present on an ObjectId but not on a string:

await removeUser(deleteUser.id);

Upon correcting this mistake by passing the ObjectId instead, everything functioned correctly:

await removeUser(deleteUser._id);

I am curious as to why TypeScript did not provide a compile time error when the argument was specified as an ObjectId but a string was being passed instead?

Edit: I have observed that the .id is declared as any, not specifically a string. Could this be a factor influencing the issue?

Answer №1

According to my observation, the .id is specified as any type, rather than a string type.

When using values of type any, you can assign them to any type without restriction.

const n: number = 'string' as any // This operation will not raise an error

The use of any serves as a way to bypass the type system. It's important to note that any is not type-safe and should be used sparingly.

For more information, refer to the official documentation:

Essentially, when using any, the compiler treats it as a way to disable type checking for that specific variable. It can be compared to adding an @ts-ignore comment before every usage of the variable.

Answer №2

Absolutely, by implementing a method to validate for any type, we can ensure that values labeled as type any are not allowed:

type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;

export async function excludeUser<Id extends Types.ObjectId>(removedUserId: IfAny<Id, never, Id>) {

If we provide any as an argument, the type of removedUserId will become never:

await excludeUser(removedUser.id);  // error, cannot assign type 'any' to type 'never'
await excludeUser(removedUser._id); // good to go

Experimentation Area

Answer №3

In the realm of Typescript, types only exist during compilation and are not present during runtime. This means that the Typescript type system is not foolproof; it cannot guarantee that a program will be error-free at runtime just because it compiles.

Regarding your query, when a variable is declared as any, you have free reign over it without any restrictions from Typescript. However, it is highly advised to use the any type with great caution.

For instance, if you define a variable obj as type any:

  • You can assign obj to any other variable (excluding those of type never)
  • You can access any properties on obj like obj.a.b.c.d
  • You can pass it to functions expecting parameters of different types, such as string

Check out this code example for a demonstration:

function onlyAcceptingNumber(a: number) {}

export async function doSomething(obj: any){
  // I can perform operations like:
  const a = obj.a * obj.b;
  // I can also access nested properties:
  console.log(obj.a.b.c.d);
  // and even call a function restricted to numbers with obj
  onlyAcceptingNumber(obj);
}

// however, there may be issues at runtime:
doSomething("123");
doSomething({ name: "John" });

In the provided scenario, although the doSomething function and both calls to it compile successfully, errors may arise during runtime.

To mitigate these risks, consider implementing measures like ESLint's no-explicit-any rule and resort to using any sparingly and as a final resort.

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

Utilizing Apollo plugin to retrieve arguments in a GraphQL resolver

I'm currently in the process of integrating a new plugin into my ApolloServer GraphQL API that is designed to log the output of the endpoint by utilizing an argument provided as the key. However, upon executing a query, it seems to appear as follows: ...

Creating a bespoke numeric input component using React Native

As I work on developing a numericInput component, my goal is to streamline the code by eliminating RNTextInput. The part that confuses me is how it utilizes React.forwardRef<RNTextInput, Props>((props, ref) => { const { onChangeText, ...rest } ...

Indicate the type of content returned by a Controller

I'm dealing with a metrics.controller.ts file that looks like this: import { Controller, Get } from '@nestjs/common'; import { ApiOperation, ApiResponse, ApiUseTags, ApiModelProperty } from '@nestjs/swagger'; import { PrometheusSe ...

What steps should I take to resolve an unhandled promise error in a React TypeScript application while making an axios POST request?

I am currently working on a .tsx file to implement adding an enterprise feature. Although I can input data, clicking the submit button does not trigger any action. My application includes a page that has a button for adding a new enterprise. Upon clickin ...

maximum number of records allowed in a nested document in MongoDB

My goal is to develop a messaging system that allows for group conversations among multiple users. Each user involved in the conversation should be able to view the entire chat, and any participant can introduce new users into the discussion if it's n ...

Tips for resolving the AWS CDK setContext error while updating beyond v1.9.0

Attempting to upgrade AWS CDK code from version 1.9.0 to version 1.152.0, I encountered a problem with the setContext code no longer being valid. The error message states ‘Cannot set context after children have been added: Tree’ The original code tha ...

You cannot call this expression. The type '{}' does not have any callable signatures. Error TS2349

An issue commonly encountered in TypeScript is error TS2349, indicating that sth has no call signatures. Various situations require different solutions, but when working with React's Context, the most effective solution I've discovered is using ...

Formatting dates in MongoDB using moment.js

Struggling to convert the createdAt date into the desired format of 'Mar 22 2023' without success. Every attempt has resulted in an 'Invalid Date' error: { $project: { _id: 0, createdAt: moment('2023-03-22T04:40:02. ...

Error: Attempting to access the 'tokenType' property of an undefined object is not allowed

We encountered an error while attempting to embed a report using the Power BI Angular library. TypeError: Cannot read properties of undefined (reading 'tokenType') at isSaaSEmbedWithAADToken (reportEmbed?navContentPaneEnabled=false&uid=am ...

Is there a way to transfer information from Postgresql to mongoDB using Java programming?

I am currently working on transferring data from a PostgreSQL database to MongoDB. I have managed to create a JSON string and store it in a MongoDB collection, but only the first entry is being stored. Below is my code snippet: public class JsonToBson { ...

When a selection is made in React MUI Virtualized Autocomplete, the autocomplete menu scrolls back to the top

I am currently using reactMUI autocomplete with virtualization because the listbox is expected to contain thousands of items. The virtualization feature works fine, but when I add an onchange function, the listbox automatically scrolls back to the top wh ...

Has the delete function API stopped working, failing to remove any items from the array as expected?

After attempting to remove a post from view, it appears to be successfully removed. However, upon revisiting the provider's route, all previous members of the array can still be found via the route below. Surprisingly, when in the route of /posts, the ...

Importing CSS properties from MUI v5 - A comprehensive guide

I'm working with several components that receive styles as props, such as: import { CSSProperties } from '@material-ui/styles/withStyles' // using mui v4 import because unsure how to import from v5 paths import { styled } from '@mui/mat ...

Resolving a persistent AngularJS 1 constant problem with Typescript

I'm currently developing an application using TypeScript and AngularJS 1, and I've encountered a problem while trying to create a constant and passing it to another class. The constant in question is as follows: module app{ export class A ...

What is the best way to ensure that the operations are not completed until they finish their work using RX

Is there a way to make RXJS wait until it finishes its work? Here is the function I am using: getLastOrderBeta() { return this.db.list(`Ring/${localStorage.getItem('localstorage')}`, { query: { equalTo: fa ...

Mongo does not support restoring user passwords

Here is the situation I am facing: Perform a Mongo database dump (using the command mongodump) Change the password of one of the admin users Restore the Mongo database (using the command mongorestore) UPDATE: When doing the database dump, I executed th ...

Is there a way to trigger an image flash by hovering over a button using the mouseover feature in AngularJS2?

When I hover over the 'click me' button, I want an image to appear on the webpage. When I stop hovering, the image should disappear using the mouseover option. This is what I attempted in my app.component.ts and my.component.ts files: Here is t ...

Using TypeScript and controllerAs with $rootScope

I am currently developing an application using Angular 1 and Typescript. Here is the code snippet for my Login Controller: module TheHub { /** * Controller for the login page. */ export class LoginController { static $inject = [ ...

API endpoint generating a Vue component as a rendered output

In the process of developing a document templater service, I am faced with the challenge of handling numerous document templates (contracts, protocols, etc.) written in Vue. The concept revolves around clients sending props in the body, which are then pass ...

"TypeORM's createConnection function on MacOS with PG database returns a Pending status even when using

Running MacOS Catalina version 10.15.4 To replicate the issue, follow these steps using the quick guide: npm install typeorm --save npm install reflect-metadata --save npm install @types/node --save npm install pg --save npm install typeorm -g typeorm in ...