Typescript: the type system fails to validate what appears to be unquestionably correct

An error occurs during compilation in the function getWrapper:

type Wrapper<K> = {
    value: K
}

type Wrappers = {
    [K in 'henk' | 'piet']: Wrapper<K>
}
const wrappers: Wrappers = {
    'henk': { value: 'henk' },
    'piet': { value: 'piet' }
}

function getWrapper<K extends keyof Wrappers>(k: K): Wrapper<K> {
    return wrappers[k]
}

The error message indicates that wrappers[k] is of type

Wrapper<'henk'> | Wrapper<'piet'>
, but it should recognize that wrappers[k] is actually Wrapper<K>. Is there a way to assist Typescript in determining this?

Answer №1

UPDATE: As of the release on 2019-05-30, TypeScript 3.5 has brought in smarter union type checking. However, this update does not address the specific issue mentioned here. This is likely due to the usage of a generic type K instead of a union of defined concrete types. Therefore, the solution provided below remains unchanged for now.


It seems that the core problem lies in how TypeScript handles unions, which may be different from what you would expect. For instance, consider the following scenario:

declare const innerUnion: { foo: string | number };
const outerUnion: { foo: string } | { foo: number } = iU; // error

In this case, TypeScript does not automatically narrow down the type of outerUnion based on the type of

innerUnion</code. The decision not to do so appears to be practical, as such reduction could lead to incorrect outcomes when there are additional properties involved:</p>

<pre><code>declare const iU: { foo: string | number, bar: string | number };
const oU: { foo: string, bar: string } | { foo: number, bar: string } = iU; // error

The above error serves a purpose, considering that iU might be something like { foo: 0, bar: '' }.

According to TypeScript, K can only be of type

'henk' | 'piet'</code, leading to the output of the function being either <code>Wrapper<'henk'>
or Wrapper<'piet'>. Since TypeScript doesn't perform such union reduction, it flags this as an error.


So, why does the return value appear as

Wrapper<'henk'> | Wrapper<'piet'></code? It's because indexing into objects using a union of keys results in a union of property values within that object.</p>

<p>A possible solution to your issue lies in utilizing a <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#keyof-and-lookup-types" rel="nofollow noreferrer">lookup type</a> to represent the indexing operation:</p>

<pre><code>function getWrapper<K extends keyof Wrappers>(k: K): Wrappers[K] {
    return wrappers[k]; // this should work
}

This implementation should align with your requirements. Best of luck!

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

Balancing website speed with capturing product impression

I've been tasked with capturing impressions of all the products visible in the viewport on a website that features thousands of products. To achieve this, I implemented a directory and utilized the IntersectionObserver, which was referenced within the ...

Ways to generate a collection of promises using array.reduce?

I'm currently working on refactoring an array.map function that iterates over an array and returns an array of promises. The task at hand is to switch from using .map to .reduce. However, after implementing .reduce without altering the business logic, ...

Preventing image flickering in SvelteKit: A guide

Upon the initial loading of a website, you may notice that the images tend to flicker or flash when transitioning between them. However, once these images are stored in the browser's cache, subsequent visits to the site will display the images seamles ...

Populating the DOM with a mix of strings and HTMLDivElements by iterating through an array using *ngFor

I have a specific layout requirement that needs to resemble this example: https://i.sstatic.net/4kP2q.png The desired layout should utilize CSS properties like display: grid; someFunction(data) { this.data = data; ...

Unable to send a function as props to a child component in TypeScript

Within my application, I have a parent component that holds a state and a setState function. This state and function are then passed down to a child component in order to retrieve values (such as input field data). When the function is triggered in the chi ...

What is the implication when Typescript indicates that there is no overlap between the types 'a' and 'b'?

let choice = Math.random() < 0.5 ? "a" : "b"; if (choice !== "a") { // ... } else if (choice === "b") { This situation will always be false because the values 'a' and 'b' are completely disti ...

unable to locate the custom npm package within my service

There is a similar inquiry posted here: My custom NPM Package is not found, but unfortunately, the solution provided did not fix my issue. I am encountering an error stating: "Could not find a declaration file for module '@dc_microurb/common' ...

Retrieve information from an axios fetch call

Having an issue with the response interface when handling data from my server. It seems that response.data.data is empty, but response.data actually contains the data I need. Interestingly, when checking the type of the last data in response.data.data, it ...

What is the process for obtaining an AccessToken from LinkedIn's API for Access Token retrieval?

We have successfully implemented the LinkedIn login API to generate authorization code and obtain access tokens through the browser. https://i.sstatic.net/0dfxd.png Click here for image description However, we are looking to transition this functionality ...

"Angluar4 is throwing an error: it's unable to read the property 'iname' of

This is the code snippet from item.ts file:- export interface item{ $key?:string; available?:boolean; countable?:boolean; iname?:string; price?:string; desc?:string; image?:string; } The items component item.componenet.ts looks like this:- import { Com ...

Error encountered during Angular production build: Attempting to assign value to a reference or variable not possible

Encountering issues building the production version of my Angular app. The IDE console only displays this message: ERROR in Cannot assign to a reference or variable! To successfully build, I need to include these options: --aot=false --buildOptimizer ...

Unable to successfully process HTTP Request Unsubscribe commands

When working with my component, I am retrieving data from a JSON file through services and subscribing to it. There is a condition check in place to stop the subscription once a specific criteria is met, but unfortunately, it doesn't seem to be workin ...

Tips for activating automatic building of packages when utilizing pnpm install?

Our unique project is utilizing a combination of pnpm, workspace, and typescript in adherence to the monorepo standard. Upon cloning the repository, we execute a pnpm install command to download dependencies and establish links between local packages. De ...

Implementing a Typescript hook using useContext along with an uninitialized context object

I am currently attempting to develop a custom hook called useAuth in React 17 with TypeScript. While my solution is somewhat functioning, it requires the following syntax when utilizing the hook methods: const auth = useAuth(); // Do other stuff ...

The property is accessed prior to being initialized

In my code, I have a class defined as follows : export class Group { id: string; name: string = ''; type: 'local' | 'ldap' = 'local'; members: number[] = []; This class is being used in my applicatio ...

Declarations of Typescript React for Props for Specific Element

I am trying to specify types for certain elements like <button> or <input>, but I am unable to differentiate between specific element types. Here is an example: interface Props{ component: React.ComponentProps<"button"> | nev ...

Encountering an Error on Building Android with Ionic 2 RC0 and Angular 2: ngc error during symbol values resolution

An error occurs when trying to build the Android application using the command ionic build android. The error message reads: "ngc: Error: Error encountered resolving symbol values statically. Reference to a local (non-exported) symbol 'dictionary&apo ...

Begin a TypeScript project within the IntelliJ IDEA 2019.2 Community edition

Creating a TypeScript project in IntelliJ IDEA 2019.2 Community edition I'm trying to setting up a TypeScript project in IntelliJ IDEA 2019.2 Community edition so I can easily navigate through the classes, but I can't seem to find the option in ...

Enabling Cross-Site Request Forgery (CSRF) through Angular's HttpClientModule is causing an error message to appear: TS2552 -

As a novice in front-end development, I am looking to incorporate CSRF tokens into certain requests within a frontend application. The app is built using Angular version 12.2.17, and I am following the guidelines outlined in the Angular documentation: http ...

Is Angular CLI incorrectly flagging circular dependencies for nested Material Dialogs?

My Angular 8 project incorporates a service class that manages the creation of dialog components using Angular Material. These dialogs are based on different component types, and the service class is designed to handle their rendering. Below is a simplifie ...