The TypeScript error ts2322 occurs when using a generic constraint that involves keyof T and a

Trying to create a generic class that holds a pair of special pointers to keys of a generic type. Check out an example in this playground demo.

const _idKey = Symbol('_idKey')
const _sortKey = Symbol('_sortKey')

export interface BaseStoreConfig<T, Tid extends keyof T, Tsk extends keyof T | undefined> {
  idKey?: Tid
  sortKey?: Tsk
}

export class BaseStore<T, Tid extends keyof T & string, Tsk extends keyof T | undefined> {
  public [_idKey]: keyof T | 'id'
  public [_sortKey]?: keyof T | undefined

  constructor({
    idKey = 'id', // Errors, see below
    sortKey,
  }: BaseStoreConfig<T, Tid, Tsk>) {
    this[_idKey] = idKey
    this[_sortKey] = sortKey
  }
}

A ts2322 Error is thrown (tried various constraints for Tid, still facing the error)

Type 'string' is not assignable to type 'Tid'.
  'string' can be assigned to 'Tid', but 'Tid' may have a different subtype of 'string'.ts(2322)

Although I grasp the concept of this error, it's puzzling in this scenario. How can a subtype of string not be compatible with this type? Any suggestions on how to define this constraint?

Answer №1

It appears that Typescript is struggling to handle different types for the same value, such as idKey, depending on whether it is viewed from the caller's perspective (Tid or undefined) or from the implementer's side (Tid or "id"). This issue is similar to others like those reported in microsoft/TypeScript#42053. However, the timeline for resolving these bugs remains uncertain.

The constructor parameter is annotated as

BaseStoreConfig<T, Tid, Tsk>
, where the idKey property is of type Tid | undefined. When attempting to assign a default value of "id" to it, the compiler flags it as an error due to the mismatch between "id" and Tid. The change in TypeScript behavior post version 3.9 results in an error mentioning string rather than specifically "id". Reverting to version 3.9 reveals an explicit error referencing "id".


A possible solution might be to avoid setting default values within destructuring due to the challenge of accommodating two different types for the same value. Instead, consider moving the default value assignment to the body of the constructor:

constructor({
    idKey, sortKey,
}: BaseStoreConfig<T, Tid, Tsk>) {
    this[_idKey] = idKey ?? "id" // works fine
    this[_sortKey] = sortKey
}

By making this adjustment, the code compiles without any errors.

Access Playground link here to view the code

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

Hapi and Bell's attempt at authenticating with Twitter was unsuccessful

Currently, I have developed a basic backend API that requires multiple authentications. My current challenge is connecting to the Twitter API using Bell. However, instead of displaying the authentication page for the app, an error is being shown: {"statusC ...

Angular 2: Issue with data table not updating after item deletion

I need assistance with updating a data table after deleting an item. The database is updated correctly when I delete an item, but the table does not automatically refresh to reflect the changes. managenews.component.ts import { Component, OnInit } from ...

The declared type 'never[]' cannot be assigned to type 'never'. This issue is identified as TS2322 when attempting to pass the value of ContextProvider using the createContext Hook

I'm encountering an issue trying to assign the state and setState to the value parameter of ContextProvider Here's the code snippet:- import React, { useState, createContext } from 'react'; import { makeStyles } from '@material-ui ...

Creating a currency input field in HTML using a pattern textbox

In a project using HTML, Angular 2, and Typescript, I am working with a textbox. How can I ensure that it only accepts numbers along with either one dot or one comma? The input should allow for an infinite number of digits followed by a dot or a comma and ...

Develop an interface in TypeScript for intricate data structures

Displayed below is a variable that contains a collection of objects: scenes = { sky: { image: 'assets/1.jpg', points: { blue_area: { x: 1, y: 2 }, } }, blue_area: { image: & ...

The function 'appendChild' is not recognized on the type 'unknown'.ts(2339)

I'm encountering an issue while trying to integrate the Utterances component into my articles. Upon attempting to build the site, I receive the following error message: "Property 'appendChild' does not exist on type 'unknown' ...

TypeScript: Unable to fetch the property type from a different type

Currently, I'm using create-react-app with its TypeScript template. However, I encountered an issue while attempting to retrieve the type of the property 'pending' in 'GenericAsyncThunk', similar to how it's done in the redux- ...

A guide to sending epoch time data to a backend API using the owl-date-module in Angular

I have integrated the owl-date-time module into my application to collect date-time parameters in two separate fields. However, I am encountering an issue where the value is being returned in a list format with an extra null value in the payload. Additiona ...

Once the Angular project has been initialized, the Button disable attribute cannot be modified

In my Ionic-Angular project, I am creating registration pages where users input their information in multiple steps. For each step, there is a button that remains disabled until the correct information is entered. An issue arises when transitioning to the ...

Tips for passing multiple items for the onselect event in a ng-multiselect-dropdown

I've got a multi-select dropdown with a long list of options. Currently, when I choose a single item, it triggers the Onselect event and adds data from the newArrayAfterProjectFilter array to the myDataList based on certain conditions in the OnselectE ...

Encountering a 403 error when attempting to upload files to Google Cloud Storage (GCS) using Signed URLs

The main aim is to create a signed URL in the api/fileupload.js file for uploading the file to GCS. Then, retrieve the signed URL from the Nextjs server through the nextjs API at localhost://3000/api/fileupload. Finally, use the generated signed URL to upl ...

A new interface property type that is customized based on the type property that is passed in

My dilemma lies in a generic interface with a field depending on the passed type. I'm exploring the possibility of having another field that can accept any type from the passed type. For instance: interface sampleObject { name: fullName age: n ...

"Exploring the process of creating a custom type by incorporating changes to an existing interface

One of the challenges I'm facing is defining an object based on a specific interface structure. The interface I have looks like this: interface Store { ReducerFoo : ReducerFooState; ReducerBar : ReducerBarState; ReducerTest : ReducerTestSt ...

Filtering an array using criteria: A step-by-step guide

Currently, I am developing a system for Role Based permissions that involves working with arrays. Here is an example of the array structure I have: let Roles = { [ { model: 'user', property: 'find', permission: 'allow' ...

Issue with NullInjectorError: Failure to provide a custom component - Attempting to add to providers without success

I keep encountering errors during my test attempts... Despite looking into similar issues, I am still facing problems even after adding my custom LoginComponent to app.module.ts providers. It is already included in the imports section. app.module.ts @Ng ...

What is the best way to organize a collection of objects by a specific characteristic in Typescript?

Imagine you have an array of objects with the following structure: type Obj = { id: number, created: Date, title: string } How can you effectively sort this array based on a specific property without encountering any issues in the type system? For ...

Error: Module '/node_modules/.vite/deps/react-pro-sidebar.js?v=913080ef' does not export 'ProSidebar' as requested

Using the pro-side-bar library in React is causing an issue for me. When I run the code, the console shows the following error using the dev tools: Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/react-pro-sidebar.js?v=913080ef& ...

Adding an item into a list with TypeScript is as simple as inserting it in the correct

I am working with a list and want to insert something between items. I found a way to do it using the reduce method in JavaScript: const arr = [1, 2, 3]; arr.reduce((all, cur) => [ ...(all instanceof Array ? all : [all]), 0, cur ]) During the fir ...

React waitforelement fails to work in conjunction with asynchronous calls

I am currently experimenting with a straightforward login form that includes an asynchronous call in React using TypeScript and classes. Here is how my component appears: import * as React from 'react'; import { LoginService } from './servic ...

Sorting through a list of strings by checking for a specific character within each string

After spending years dabbling in VBA, I am now delving into Typescript. I currently have an array of binary strings Each string represents a binary number My goal is to filter the array and extract all strings that contain '1' at position X I ...