Can TypeScript allow the usage of variables as type declarations?

Can someone help me understand how to avoid using this particular pattern (b[firstCriteria] as number)? I need the function to be type-safe and only allow passing an existing key from the object inside the array.

I'm encountering an error in TypeScript, and I've come across two potential solutions:

  1. One approach is to include [key: string]: number in the type definition, but this allows any key to be passed.

    interface BaseHighLightsRes {
      id: number;
      manager_rank: number;
      player_name: string;
      entry_name: string;
      [key: string]: number;
    }
    
  2. The second option involves adding as Number.

    import { BaseHighLightsRes } from "../types/apiResponce";
    
    export const sortHighlight = <T extends BaseHighLightsRes>(
      array: T[],
      firstCriteria: keyof T,
      secondCriteria: keyof T = "manager_rank"
    ): void => {
      array.sort(
        (a, b) =>
          (b[firstCriteria] as number) - (a[firstCriteria] as number) ||
          (a[secondCriteria] as number) - (b[secondCriteria] as number)
      );
    };
    
    

I'm uncertain if my type implementation is accurate. How can I ensure that TypeScript correctly infers the type?

Answer №1

Despite encountering issues with my code, I decided to share my attempt.

The KeysOfType function is designed to extract keys with values of a specific type from a given record. In this case, we apply it to restrict firstCriteria and secondCriteria to keys only containing number values. This ensures that when we manipulate and retrieve these properties, they are guaranteed to be of type number. However, I faced persistent errors, prompting me to utilize // @ts-ignore to overlook the errors. Given the simplicity of the code, I believe this workaround may suffice.

Updated code snippet:

interface BaseHighLightsRes {
  id: number;
  manager_rank: number;
  player_name: string;
  entry_name: string;
}


type KeysOfType<TRecord extends Record<any, any>, TargetType> = { 
  [K in keyof TRecord]: TRecord[K] extends TargetType ? K : never 
}[keyof TRecord];

export const sortHighlight = <T extends BaseHighLightsRes>(
  array: T[],
  firstCriteria: KeysOfType<T, number>,
  // @ts-ignore
  secondCriteria: KeysOfType<T, number> = "manager_rank"
): void => {
  array.sort(
    (a, b) => {
      // @ts-ignore
      return b[firstCriteria] - a[firstCriteria] ||
      // @ts-ignore
        a[secondCriteria] - b[secondCriteria]
    }
  );
};

// Works fine
sortHighlight([{
  entry_name: 'fsdf',
  id: 123,
  manager_rank: 123,
  player_name: 'fsdf'
}], 'id', 'manager_rank');

// Error! Second argument is not valid
sortHighlight([{
  entry_name: 'fsdf',
  id: 123,
  manager_rank: 123,
  player_name: 'fsdf'
}], 'player_name', 'master_rank');

Bonus addition (not implemented yet) Creates a record type consisting exclusively of values matching TargetType.

type RecordWithKeysOfType<TRecord extends Record<any, any>, TargetType> = Pick<TRecord, KeysOfType<TRecord, TargetType>>;

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

Mastering Vue3: Typed Component Instance Template Refs with Exposed Methods

In my project, I am working with a component called A that has a method called send. Here is an example of how Component A is structured in A.vue: <script setup lang="ts"> function send(data: string) { console.log(data) } defineExpose({ ...

How can I dynamically reference two template HTML files (one for mobile and one for desktop) within a single component in Angular 6?

Here is the approach I have taken. Organizational structure mobile-view.component.html <p> This content is for mobile view </p> desktop-view.component.html <p> This content is for desktop view </p> mobile.component.ts import ...

Searching for a streamlined approach to retrieve a segment of a string

I'm currently working with JavaScript and TypeScript. Within my code, I encountered a scenario where I have a string that might contain certain tags indicating importance or urgency. Here are a couple of examples: A: "Remind me to go to the store to ...

Is it possible for TypeScript to convert objects while preserving type annotations?

Apologies for my limited English skills, but I will do my best to explain my dilemma. I am looking to create a TypeScript function that can replace the keys of an Object. For example: interface Target { name: string; ID: number; } // The functio ...

Utilizing the Chinese Remainder Theorem within JavaScript Programming

Attempting to tackle the challenge presented in part 2 of Advent of Code 2020 day 13, I came across discussions referencing the intriguing concept known as the Chinese Remainder Theorem. Various approaches were explored, including utilizing an older implem ...

Adding properties to React Component

Due to security reasons, I am required to update the ant design library in my codebase from version 3 to 4. In the past, this was how I used the icon: import { Icon } from 'antd'; const Demo = () => ( <div> <Icon type="smile" ...

Angular Animation not smoothly transitioning on Internet Explorer 11 and Firefox, but functioning correctly on Chrome

Chrome seems to be handling my Angular animation attached to a div (where the height goes from 0 to '*') just fine. I've made sure to import all necessary polyfills and install web-animations-js. However, when it comes to IE and Firefox, th ...

The Intl.DateTime formatter consistently generates incorrect times even after refreshing the component in a React application

Our component is responsible for receiving information from the backend and rendering it. The properties of the component are defined as: interface CitizenshipProps { citizenship?: Citizenship; name?: string; lastName?: string; onUpdateClic ...

Using Typescript to configure a custom proxy in a Create React App

I am looking to implement request proxying from a Create React App to a separate API server, with the ability to set the server dynamically or using environment variables. While I have followed the guide on manually configuring the proxy, I am encounteri ...

Navigating through elements in Angular

I am working with multiple Angular components housed within a display:flex div container. I am fetching datatable from an API, and it contains the same number of rows as there are components. Each row in the datatable corresponds to data for each compone ...

Elements are unresponsive to scrolling inputs

My Ionic 2 input elements are not scrolling to the top when the keyboard is shown. I've tried everything I could find on Google, making sure the keyboard disable scroll is set to false. However, I still can't figure out what's causing the sc ...

The parameter 'any' cannot be assigned to the parameter 'never' - Array provided is incompatible

Currently delving into TypeScript and encountering an issue while setting a reducer in redux Toolkit. Here's the code snippet in question: const testSlice = createSlice({ name: "test", initialState: [], reducers: { callApi: (state, ...

Implementing a back button in an RTL layout with Ionic 2

Just starting an Ionic 2 app in Arabic language requires a RTL layout. I decided to go with the side menu template. Adding the following line for configuring the app to RTL perfectly changed everything's direction, except for the back button which st ...

Having trouble locating the export in the TypeScript module

Having a situation where there is a file with an exported object: let btypes:{[key:string]:any} = { "key1":val, //... } export {btypes} I even attempted to use export default btypes Upon importing it using: import {btypes} from "../types& ...

Update Observable by assigning it a new value of transformed information using the async pipe and RXJS

My service always returns data in the form of Observable<T>, and unfortunately, I am unable to modify this service. I have a button that triggers a method call to the service whenever it is clicked. This action results in a new Observable being retu ...

The 'resp' parameter is assumed to have an unspecified type, shown as 'any'. This is an error in Angular

} ErrorHandler(response){ console.debug(response.json()); } DataHandler(response){ this.ClientModels = response.json(); } I have developed two functions to handle error and success responses, but an error message is showing up saying "para ...

Using MUI DatePicker and react-hook-form to implement a date picker in the format DD/MM/YYYY

I have developed a custom datePicker component that combines react-hook-form and Material UI. However, I am encountering an issue where the values are being displayed in the format: "2024-04-10T22:00:00.000Z" Below is the code snippet: import { Localizati ...

The Art of Dynamic Component Manipulation in Angular

The current official documentation only demonstrates how to dynamically alter components within an <ng-template> tag. https://angular.io/guide/dynamic-component-loader My goal is to have 3 components: header, section, and footer with the following s ...

Sending binary information from a .net core web api to a typescript application

I currently have a .net core 3.0 web api application connected to an angular 8 client. While I have successfully transferred data between them using json serialization, I am now looking for a way to transfer a bytes array from the api to the client. After ...

Issue with Component in Angular not functioning properly with proxy construct trap

Currently working with Angular 17, I have a straightforward decorator that wraps the target with Proxy and a basic Angular component: function proxyDecorator(target: any) { return new Proxy(target, { construct(target: any, argArray: any[], newTarget: ...