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

Building a Model Class with redux-orm and TypeScriptCreating a new Model Class with

I've been successfully using redux-orm with JavaScript, however, I'm facing issues when trying to convert my code to TypeScript. Even though I have already implemented the render() method in my Folder Model Class, the TypeScript transpiler is sh ...

ng2-idle server side rendering problem - Uncaught ReferenceError: document is undefined

Can ng2-idle be used for idle timeout/keepalive with pre-rendering in Angular 4? I followed this link for implementation: It works fine without server pre-rendering, but when I add rendering back to my index.html, I keep getting the following error: Exce ...

What could be the reason it's not functioning as expected? Maybe something to do with T extending a Record with symbols mapped

type Check<S extends Record<unique, unknown>> = S; type Output = Check<{ b: number; }>; By defining S extends Record<unique, unknown>, the Check function only accepts objects with unique keys. So why does Check<{b:number}> ...

Testing the throwing of errors when running Karma by utilizing sinon.spy on global functions like parseInt

I'm currently facing an issue with monitoring the usage of parseInt within my function. This is a Proof of Concept for integrating TypeScript into our company's workflow. I've tried following two different tutorials on testing Sinon, but no ...

Encountered an issue: The type 'Usersinterface' is not meeting the document constraints

Below is a screenshot displaying an error: https://i.stack.imgur.com/VYzT1.png The code for the usersinterface is as follows: export class Usersinterface { readonly username: string; readonly password: string; } Next, here is the code for users ...

Choosing from a list in Angular

I'm trying to make a dropdown menu that shows options in the format "code-description", but only displays the "code" portion when an option is selected. For example, showing "A-Apple" in the dropdown, but displaying only "A" when chosen. I am able to ...

TypeScript enables the use of optional arguments through method overloading

Within my class, I have defined a method like so: lock(key: string, opts: any, cb?: LMClientLockCallBack): void; When a user calls it with all arguments: lock('foo', null, (err,val) => { }); The typings are correct. However, if they skip ...

Transforming seconds into years, months, weeks, days, hours, minutes, and seconds

Can anyone help me modify Andris’ solution from this post: Convert seconds to days, hours, minutes and seconds to also include years, months, and weeks? I am currently running this code: getDateStrings() { console.log(req_creation_date); const toda ...

Restricting array elements through union types in TypeScript

Imagine a scenario where we have an event type defined as follows: interface Event { type: 'a' | 'b' | 'c'; value: string; } interface App { elements: Event[]; } Now, consider the following code snippet: const app: App ...

Transforming res.json() into an Array of Objects

I am dealing with a Java webservice that outputs a list of Json objects with specific properties: public class Oferta { private int id; private String categoria; private String descricao_oferta; private String anunciante; private double valor; private boo ...

Choosing radio buttons within rows that contain two radio buttons using ngFor

This section showcases HTML code to demonstrate how I am iterating over an array of objects. <div class="row" *ngFor="let item of modules; let i = index;"> <div class="col-md-1 align-center">{{i+1}}</div> <div class="col-md- ...

Injection of environmental variables into app services

Through the use of Nx, I have created multiple apps that each have their own environment with different API URLs. The Nx Workspace library includes shared services that are utilized among all apps, however, it is necessary to pass the environment-api-url w ...

Encountering compilation errors during the vue-cli build process

My Vue 2.2.3 application is experiencing difficulties in the build process due to 4 TypeScript-related errors that are perplexing me. This is the error output displayed on the console: Failed to compile with 4 errors ...

I'm seeing an issue where my SafeResourceUrl is being displayed as undefined within a function of the identical class

export class ClassName implements OnInit { url: string = "{{'content.url' | translate}}"; urlSafe: SafeResourceUrl; constructor(public sanitizer: DomSanitizer, private translate: TranslateService) { } ngOnInit() { ...

Encountering a ReactJs and TypeScript error: "menuItems.map is not a function, issue with map method"

Greetings! I am currently working on implementing the logic of using useState and mapping an array to show only one dropdown item at a time. Below is my array structure with tags (menu name, links (to router), icon (menu icon), and if there are dropdown i ...

Ways to efficiently update the API_BASE_URL in a TypeScript Angular client generated by NSwag

Is it possible to dynamically change the API_BASE_URL set in my TypeScript client generated by NSWAG? I want to be able to utilize the same client with different API_BASE_URLs in separate Angular modules. Is this achievable? Thank you for your assistance. ...

Discovering the breakpoints for Angular ng-bootstrapUncover the angular ng

Utilizing ng-bootstrap in my latest project has allowed me to easily create a grid with breakpoints, like so: <div class="row"> <div class="col-sm-12 col-md-6 col-xl-4"></div> </div> Although these breakpoints are convenient, ...

Is there a way to modify the antd TimePicker to display hours from 00 to 99 instead of the usual 00 to 23 range?

import React, { useState } from "react"; import "./index.css"; import { TimePicker } from "antd"; import type { Dayjs } from "dayjs"; const format = "HH:mm"; const Clock: React.FC = () =& ...

Objects in the array are failing to sort in the expected sequence

I am facing an issue with sorting an array of objects by a date property using the lodash function orderBy. I have tried to sort it in both ascending and descending order. var searchObj = [{id: 1, postDate: '2/24/2016 5:08 PM'}, ...

Using act() in React/Jest/MSW causes errors when waiting for a response

As I delve into learning how to unit test with React, my focus has shifted towards using TypeScript. Unfortunately, the course I am taking does not cover most errors related to TypeScript. In my testing journey, I have set up a simple testing function with ...