What could be causing Typescript to inaccurately infer the type of an array element?

My issue revolves around the object named RollingStockSelectorParams, which includes arrays.

I am attempting to have TypeScript automatically determine the type of elements within the specified array additionalRsParams[title].

The main question: why does

ValueType<RollingStockSelectorParams, T>
show up as unknown in this scenario?

Additionally, I am curious about why indexOf assumes it is Comfort even though it cannot infer the actual type during compilation.

indexOf(searchElement: Comfort, fromIndex?: number | undefined)

The argument of type 'ValueType<RollingStockSelectorParams, T>' cannot be assigned to a parameter of type 'Comfort'. Type 'unknown' is not assignable to type 'Comfort'.(2345)

export type ValueType<T, K extends keyof T> = T[K] extends (infer U)[] ? U : never;

export type Comfort = 'AC' | 'HEATING' | 'STANDARD';

export type RollingStockSelectorParams = {
  comfortLevels: Comfort[];
  tractionModes: string[];
  electricalProfiles: (string | null)[];
  powerRestrictions: (string | null)[];
};

function f<T extends keyof RollingStockSelectorParams>(
value: ValueType<RollingStockSelectorParams, T>,
title: T,
additionalRsParams: RollingStockSelectorParams
) {
const index = additionalRsParams[title].indexOf(value);
}

Answer №1

Considering that ValueType<T, K> is categorized as a conditional type, and given that the type of value is

ValueType<RollingStockSelectorParams, K>
for a generic K within the scope of function f(), it can be concluded that value falls into the category of a generic conditional type. The TypeScript type checker typically holds off on evaluating such types extensively. Instead, it treats the type as somewhat opaque, only raising objections if an attempt is made to assign anything other than the same opaque type.

When attempting to use it in the manner depicted, the type checker reaches a point where it declares the assignment not feasible. The specific structure of ValueType<T, K> employs conditional type inference to derive the outcome. Since the resulting U type is inherently constrained to unknown by default, the compiler raises caution due to the potential wide variability of the U type being equated with unknown.

There have been numerous mentions in GitHub issues about generic conditional types regarding this behavior. In essence, there are limitations in addressing this scenario comprehensively, though there may be isolated instances where support could be extended. One instance closely resembling the current context is highlighted in microsoft/TypeScript#52489.


If you are certain that an array type is involved, there's no necessity for employing conditional type inference to ascertain its element type. Utilizing indexing with number would suffice:

export type ValueType<T extends Record<K, any[]>, K extends keyof T> =
    T[K][number]

While this approach might not directly address your situation, at least the compiler would identify the result as string | null rather than merely unknown.


Inquiries raised on Stack Overflow should ideally focus on a single question. Hence, I won't delve deeply into your secondary query. To briefly explain why indexOf() anticipates Comfort, this pertains to the intersection of possible element types. Essentially,

Comfort & string & (string | null)
simplifies to just Comfort. Due to the challenge in interpreting
additionalRsParams[title].indexOf()
generically, the compiler reverts to the specific constraint, leading to a union of functions that necessitates an intersection of arguments, in line with enhanced calling behavior for union types.


The recommended coding practice, as discussed in microsoft/TypeScript#47109, advocates building everything around generic indexing within a fundamental key-value interface or mapped types based on that interface. Here's how it looks:

interface Rolling {
    comfortLevels: Comfort,
    tractionModes: string,
    electricalProfiles: string | null,
    powerRestrictions: string | null
}

function g<K extends keyof Rolling>(
    value: Rolling[K],
    title: K,
    additionalRsParams: { [K in keyof Rolling]: Rolling[K][] }
) {
    const index = additionalRsParams[title].indexOf(value);
}

However, I refrain from delving further since the primary inquiry isn't focused on "how to make the compiler understand this", but rather on questioning why value is perceived as unknown.

Access the code in Playground

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

Creating a responsive class getter with Vue.js 3 using the Composition API: a guide

How can I set up a class instance property to reactively display an error message when authentication fails? UserModel.ts export class User { private error: string; set errorMessage(errorMessage: string) { this.error = errorMessage; } get err ...

Deliver transcluded data to the descendant element of a hierarchical roster

I understand that there have been similar questions asked before, but my situation is slightly different. I am currently constructing a nested list and I want to include custom HTML content in each grandchild element alongside some common HTML. The problem ...

Discover how to set up lazy loaded child routes within a parent route that is also loaded lazily in Angular 2

Struggling to implement lazy loading for my app has been a series of challenges. I successfully implemented lazy loading for the main route, /admin, but now I am facing issues while adding another route, /admin/login. This is what I tried: admin-router.m ...

Angular 5 is encountering an error with a recursive template, specifically a RangeError stating that the maximum call stack

Hey there, I'm currently utilizing Angular recursive template to represent arrays recursively. The code I've been following is provided in this link. My array is dynamic in nature. <ul> <ng-template #recursiveList let-list> ...

The error message "Property 'then' is not available on type 'void' within Ionic 2" is displayed

When retrieving data from the Google API within the function of the details.ts file, I have set up a service as shown below. However, I am encountering a Typescript error stating Property 'then' does not exist on type 'void'. this.type ...

Issue: Module 'stylelint' not found in Angular Project

I've been attempting to execute this command to validate all of the .scss files (and even tried with .css files) and I keep encountering this error. $ stylelint "apps/**/*.scss" It worked once before but not anymore, even after restarting my compute ...

The Dilemma of using forRoot() in Angular 2/4+ Shared Modules

After uncovering the treasure that is forRoot() while delving deeper into Angular dependency injection (DI), I find myself pondering on the best practices for its usage. I came across this method when trying to enable a lazy loaded module to access a serv ...

Tips for relocating the indicators of a react-material-ui-carousel

I am working with a carousel and dots indicators, but I want to move the indicators from the bottom to the circular position as shown in the image below. I attempted using a negative margin-top, but the indicators ended up being hidden. Is there another ...

The object[] | object[] type does not have a call signature for the methods 'find()' and 'foreach()'

Here are two array variables with the following structure: export interface IShop { name: string, id: number, type: string, } export interface IHotel { name: string, id: number, rooms: number, } The TypeScript code is as shown below ...

Issue: The function "generateActiveToken" is not recognized as a function

I encountered an issue in my Node.js project and I'm unsure about the root cause of this error. Within the config folder, there is a file named generateToken.js which contains the following code snippet: const jwt = require('jsonwebtoken'); ...

How to send variables to a function when a value changes in TypeScript and Angular

As someone who is new to Angular and HTML, I am seeking assistance with the following code snippet: <mat-form-field> <mat-select (valueChange)="changeStatus(list.name, card.name)"> <mat-option *ngFor="let i of lists"> {{i.name}} ...

Trouble with displaying cell content in ag-grid within an Angular application

I have implemented ag-grid in my Angular project and I am trying to redirect to a link when a specific cell is clicked. Currently, I have a new value coming from an API which is nested inside an object in an array. For example, the object is dto-> dat ...

Despite using Enzyme to locate a component again, the expected prop value is still not being returned

Two components are involved here - a modal and a button that is meant to open the modal by setting its isOpen prop to true. The initial state of the modal is set to false, but when the button is clicked, it should change to true. While everything works fi ...

Issue with decorators not functioning in the latest alpha version of Sequelize v7

As I was exploring sequelize v7 (alpha), I encountered multiple errors when trying out basic examples directly from their documentation. For instance, taken straight from the official documentation import { Sequelize, DataTypes, Model, InferAttributes, Inf ...

Having trouble displaying the week number in Angular Highcharts?

I am currently facing an issue with implementing highcharts in my Angular application that I am unable to resolve. My goal is to display the week number on the xAxis using the 'datetime' type. I came across this JSFiddle that seems to provide a ...

Changing the selection on multiple input fields in Angular

I am working with two select elements in my form. Based on the selected value from the first select, I am filtering data for the second select. Additionally, I have an option to add the same row of form if desired. My issue is that when I select a value fr ...

What is the best way to utilize the fresh Sanitizer API in Typescript?

Everything seems to be working well on Codepen, even without using window. It's surprising because I'm used to having to use window.x if ( 'Sanitizer' in window ) { console.log( 'sani', 'Sanitizer' in window ); } ...

Best Practices for Error Handling in Typescript

After delving into articles about error handling, a thought lingers in my mind - is throwing an exception on validation logic in the value object really the most efficient approach? Take for example this class that represents a value object: export class U ...

Specialized type for extra restriction on enum matching

In my current project, I am dealing with two enums named SourceEnum and TargetEnum. Each enum has a corresponding function that is called with specific parameters based on the enum value. The expected parameter types are defined by the type mappings Source ...

What advantages does utilizing Jasmine Spy Object provide in Angular Unit Testing?

I have a question regarding unit testing in Angular using Jasmin/Karma. Currently, I am working with three services: EmployeeService, SalaryService, and TaxationService. The EmployeeService depends on the SalaryService, which is injected into its constru ...