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

React fails to acknowledge union types

I have the following types defined: export enum LayersItemOptionsEnum { OPERATOR, HEADER, } type sharedTypes = { children: string | ReactElement; }; type LayersItemStatic = sharedTypes & { label: string; option: LayersItemOptionsEnum; }; t ...

Function parameter constrained to a specific property of a generic type T

In my codebase, I have a custom function called uniqBy, which filters out duplicate items based on a specified key: export function uniqBy<T>(array: T[], key: any): T[] { const seen = {}; return array.filter(function (item) { if (item ...

Bring in a collection of classes of various types from one TypeScript file to another

In my code file exampleA.ts, I define an object as follows: import { ExampleClass } from 'example.ts'; export const dynamicImportations = { ExampleClass }; Later, in another file named exampleB.ts, I import an array that includes class types and ...

Why does Typescript not enforce a specific return type for my function?

In my custom Factory function, I need to return a specific type: type Factory<T> = () => T; interface Widget { creationTime: number; } const createWidget: Factory<Widget> = () => { return { creationTime: Date.now(), foo: &a ...

What could be the reason my RxJS Observable chain does not run again when new emissions are made?

Currently, I am facing a unique challenge while working with RxJS in an Angular service. The issue revolves around two observable chains designed to enhance a stream of notifications with user data. One chain functions correctly, allowing for multiple trig ...

Having an issue with forkJoin where the code seems to get stuck and does not continue execution after

The following script is retrieving two values from the database. I am using forkJoin for this purpose, which is a new approach for me. The reason behind utilizing this method is that there is a specific function that requires both values to be fetched bef ...

Is the autoIncrement property missing from the IDBObjectStore Interface in Typescript 1.8 lib.d.ts file?

Upon examining the specifications on various pages, it is evident that there is a specified read-only property named "autoIncrement" within the IDBObjectStore: https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore https://developer.mozilla.org/ ...

A simple way to automatically fill an input field with a mask when clicking in Angular 2

When a user clicks on this span, the following action is triggered: <span data-content="15" #Fast15 (click)="enterFastTime(Fast15)" class="quick-time">15mins</span> Users can also manually input a date in the following input field. If they ...

Extending a class with diverse types in Typescript: A guide

I have a class with multiple methods that deal with an entity referred to as "entity." class entity { entityName: string = ''; getList(): any[] { someAPI + this.entityName .... } getOne(): any{ } } Additionally, there are specifi ...

incorporating my unique typographic styles into the MUI framework

I'm currently working on customizing the typography for my TypeScript Next.js project. Unfortunately, I am facing difficulties in configuring my code properly, which is causing it to not work as expected. Can someone kindly provide assistance or guida ...

Retrieve the file from the REST API without using the window.open method

I'm looking for a method to download files from an API without using window.open(). I want the download process to start immediately upon calling the API. Currently, I am downloading an .xls file generated by a REST API using window.open() API Endpo ...

Share information by including the provider within the @component declaration in Angular

I am looking to explore a new method of passing data using providers directly within the component itself. For instance, I am curious if there is a way to pass a variable from one component to another without relying on routing or other traditional methods ...

Incorporating Imported Modules into the Final Build of a Typescript Project

In my Visual Studio Code Typescript project, I have set up some basic configurations and used npm to download libraries. One of the main files in my project is main.ts which includes the following code: import ApexCharts from 'apexcharts' var c ...

Unveiling the magic behind using jasmine to spy on a generic

I am trying to spy on a generic method in TypeScript, but Jasmine is not recognizing it. Here is the code snippet: http: HttpClient <- Not actual code, just showing type. ... this.http.get<Customer[]>(url); In this code, I am trying to mock the ...

Initiating Angular APP_INITIALIZERThe Angular APP_INITIALIZER

I am a newcomer to Angular and currently utilizing Angular6 for development purposes. I have a specific query regarding my app. Before the app initializes, I need to invoke three services that provide configurations required by the app. Let's refer to ...

Angular - Acquire reference to the <audio> element

Is there a way to access the methods of an audio tag within my component in order to implement play and pause functions based on click events? The current method I tried does not allow me to access the play() function. How can I correctly approach this? ...

Typescript patterns for creating a modular library design

Transitioning a JavaScript project to TypeScript has been challenging for me, especially when it comes to establishing a solid design pattern for the library's modularity. Main Concept The core functionality of my library is minimal. For instance, i ...

'Error: The type is missing the 'previous' property - Combining TypeScript with ReactJS'

I am quite new to using reactjs and ts. While I understand the error that is occurring, I am unsure of the best solution to fix it. Currently working with reactjs, I have created an: interface interface IPropertyTax { annul: { current: number; p ...

The confirm alert from Material UI is being obscured by the dialog

How can I ensure that a material ui dialog does not hide the alert behind it when confirming an action? Is there a way to adjust the z index of the alert so that it appears in front of the dialog? import Dialog from "@material-ui/core/Dialog"; i ...

I continue to encounter the same error while attempting to deliver data to this form

Encountering an error that says: TypeError: Cannot read properties of null (reading 'persist') useEffect(() => { if (edit) { console.log(item) setValues(item!); } document.body.style.overflow = showModal ? "hidden ...