The battle of Any, Generic Type, and Unknown in Typescript

Is it advisable to replace the type any with Generic Types?

I understand that using type any is generally discouraged as it removes type checking in TypeScript, making it unsafe. So what is a better alternative - using unknown or generic types?

For example, here is a function signature I'd like to modify:

getTranslationByKeys(keys: any): any {}

The types of keys and the return value are specified when calling the function (array, object...)

Answer №1

When considering function definitions, I believe that the strict ban on using any, often expressed as: "never use it except temporarily for transitioning from JavaScript to TypeScript," is overly simplistic. In particular, I find that the restriction against any isn't as absolute when it serves as a constraint on a generic type parameter within a function. In this context, I believe any can be quite beneficial.

I agree that any is problematic in the example you provided.

getTranslationByKeys(keys: any): any {}

This completely disregards the type system. For instance, consider this call site:

const myResult = getTranslationByKeys(keys: [1,3,4])

I have no clue if this function can process the parameters I've supplied or what the result will be once it's finished (if it even finishes):

Clearly not ideal. However, let's examine the following function typing:

function getTranslationByKeys<T extends any>(keys: T): T {}

It contains the term any. Although numerous lint rules and educational materials on TypeScript may criticize its usage unless temporary for an update, I don't see it as problematic in this scenario. Why? Because unlike employing any as an unadulterated type, here you're not completely bypassing the type system. Essentially, you still have robust type safety at the call site. For example, a call like:

const myResult = getTranslationByKeys(keys: [1,3,4])

would indeed be strongly typed. myResult would possess the type

number[]</code, and (in my view), the absence of a constraint on <code>keys
indicates to the user that any type of parameter is acceptable.

Granted, some level of type safety inside the function definition is compromised, whereby keys could potentially be anything. Sometimes, however, that's precisely what is needed. You might have a function capable of handling various input types, such as this (albeit nonsensical) function:

function getTranslationByKeys<T extends any>(keys: T): T { 
  console.log(keys)
  return keys
}

While that specific code snippet might seem absurd, my point is that there are no issues with the typing of the code. It retains strong typing at the call site and accurately represents the function in the definition. Allowing the utilization of any!

Some may argue that what I've articulated above mirrors simply writing getTranslationByKeys<T>, which is commonly seen and technically doesn't include the term any. However, this distinction doesn't alter the situation. The two statements are equivalent, and one shouldn't be favored solely because any is concealed.

Furthermore, any can prove highly beneficial within generic constraints. Take into account this example:

function getTranslationByKeys<T extends Record<string, any>>(keys: T): T {}

Here too we encounter the dreaded word any, yet it functions as a valuable constraint. It specifies that T can assume any object form—as long as it's objectively an object with string-based indices. This constraint is far more precise than merely stating T extends object. I routinely employ and appreciate this application of any within function definitions.

Could you substitute unknown here instead of any? Perhaps. Admittedly, I haven't employed unknown extensively in conjunction with generic constraints to ascertain its equivalence in behavior. From my perspective, though, unknown appears less indicative of your intentions in the aforementioned scenario. To the function's consumer, you're not saying "provide me with a string-indexed object with unknown value types"; rather, you essentially mean "you can supply a string-indexed object with any values"—precisely what any embodies!

Hence, I contend that any, utilized within the framework of constraints on generic type parameters, can offer significant value and clarity. Therefore, it should not be subject to the broad prohibition frequently associated with utilizing any as a basic type.

I would love to hear others' perspectives on this matter.

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

Simulating TypeDI service behavior in Jest

My current setup includes Node with TypeScript, TypeDI and Jest. I've been working on creating services that have dependencies on each other. For example: @Service() export class MainService{ constructor(private secondService: SecondService){} public ...

Learn how to trigger an HTTP exception after a failed command in a saga with NestJS CQRS

Currently utilizing the NestJS CQRS pattern to handle interactions between User and UserProfile entities within my system. The setup consists of an API Gateway NestJS server along with dedicated NestJS servers for each microservice (User, UserProfile, etc. ...

Testing the GET method in an Angular service: A guide

I'm currently facing an issue with my service method and unit test setup. Despite writing a unit test for the getter method, the coverage report indicates that this method is not covered. I would appreciate any advice on what might be going wrong in m ...

Unable to access the `isDragging` property in TypeScript when using the `useDrag` method from react-d

As a newcomer to utilizing react in combination with typescript, I am currently working on implementing a drag and drop feature using the react-dnd package along with typescript. I came across this helpful blog that has guided me through the process of dra ...

What could be causing the vue-property-decorator @Emit to malfunction in my Vue TypeScript file?

I am currently working with Typescript and Vuejs, where I have a child component called child.component.tsx import Vue from 'vue'; import Component from 'vue-class-component'; import { Emit } from 'vue-property-decorator'; ...

The absence of typings.json in Typescript is creating an issue

As of now, I am encountering the following error during compilation: typings.json is missing In my existing packages.json, I have included the following dependency: "devDependencies": { "typescript": "^2.6.1", ... } Do you have any suggestion ...

Implementing a GIF loader in your webpack configuration for a Typescript/React/Next.js application

Upon inserting a .gif file in my Typescript React app, an error message has surfaced. ./src/gif/moving.gif 1:6 Module parse failed: Unexpected token (1:6) You may need an appropriate loader to handle this file type, currently no loaders are configured to p ...

Is there a way to access a specific tab index in Ionic 3.20 from a child page using a function call?

Imagine having a tabs page with 3 index pages. The first index page is the home page, the second is the products page, and the third is the cart page. When navigating from the home page to the search page, there is a button that you want to click in orde ...

NextJS compilation sometimes results in undefined errors when using Sass styles

My peace lies in the sass code: .link display: inline-table text-align: center align-self: center margin: 5px 15px font-size: 20px color: black text-decoration: none transition: 0.1s ease-in-out .link:hover text-decoration: underline .l ...

Problem with Grouping of Columns in Material-UI

Having some trouble with column grouping in MUI data grid pro. I am using typescript and trying to implement column grouping, but encountering issues with the module GridColumnGroupingModel, which is used as the type definition for columnGroupingModel. Fol ...

The implementation of getStaticPaths was done independently of getStaticProps - TypeScript

I am currently in the process of setting up a new blog using a combination of nextJS, TypeScript, and sanity CMS. The homepage is already set up to display posts perfectly. Next on my list is to display the details of each post when it is clicked, based on ...

Troubles arise when compiling TypeScript to JavaScript

I have been experimenting with TypeScript, specifically for working with classes. However, I am facing an issue after compiling my TS file into JS. Below is the TypeScript code for my class (PartenaireTSModel.ts): export namespace Partenaires { export ...

Configuring environment variables during Jest execution

A variable is defined in my `main.ts` file like this: const mockMode = process.env.MOCK_MODE; When I create a test and set the variable to true, it doesn't reflect as `'true'` in the main file, but as `'false'` instead. describe ...

The VSCode Extension fails to launch after being packaged

I'm currently working on a straightforward VSCode extension that scans the active open file for any comments containing "//TODO: " and then presents a list of all TODO comments in a webview sidebar tab. While I have a functional prototype that runs s ...

What are the recommended TypeScript tsconfig configurations for running Node.js 10?

Can someone provide information on the necessary target/libs for enabling Node.js v10.x to utilize async/await without generators? I have found plenty of resources for node 8 but not as much for node 10. ...

`Is there a way to maintain my AWS Amplify login credentials while executing Cypress tests?`

At the moment, I am using a beforeEach() function to log Cypress in before each test. However, this setup is causing some delays. Is there a way for me to keep the user logged in between tests? My main objective is to navigate through all the pages as the ...

Guide on sending JSON object to Angular custom components

I have implemented a custom element in Angular 7 using the CUSTOM_ELEMENTS_SCHEMA. My app.module.ts code is as follows: export class AppModule { constructor(private injector: Injector) {} ngDoBootstrap() { this.registerCustomElements( ...

Ensure the JSON file aligns with the TypeScript Interface

I am working with a config.json file. { "profiler": { "port": 8001, "profilerCache": { "allowedOriginsRegex": ["^http:\/\/localhost:8080$", "i"] } }, "database": { "uri": "mongodb+srv://...", "dbName": "profiler", ...

Angular data table is currently displaying an empty dataset with no information available

While attempting to display a data table in Angular JS, an issue arose where the table showed no available data despite there being 4 records present. Refer to the screenshot below for visual reference. This is the approach I took: user.component.ts imp ...

Enhancing JavaScript functions with type definitions

I have successfully implemented this TypeScript code: import ytdl from 'react-native-ytdl'; type DirectLink = { url: string; headers: any[]; }; type VideoFormat = { itag: number; url: string; width: number; height: number; }; type ...