Combining different types in object keys helps prevent errors when working with TypeScript

Let's create a function

type VarietyType = 'choice1' | 'choice2'
const myFunction = (arg: Partial<Record<VarietyType, number>>) => {
  console.log(arg)
}

When calling it with an argument of the incorrect type

myFunction({choice1: 1, ['choice3' as 'choice3']: 2})

An error occurs

Argument of type '{ choice1: number; option3: number; }' is not assignable to parameter of type 'Partial<Record<VarietyType, number>>'. Object literal may only specify known properties, and '['option3' as 'option3']' does not exist in type 'Partial<Record<VarietyType, number>>'

This behavior is expected. However, changing the type of the option3 argument to a union type removes the error, which is surprising. This doesn't trigger an error:

myFunction({option1: 1, ['option3' as 'option3' | 'option4']: 2})

But why is that?

Answer №1

One issue with TypeScript is its current limitation or lack of feature where computed property keys with types other than single string literals are widened to string, resulting in unexpected index signatures for objects.

Take a look at the inferred type of an object literal:

const v = { option1: 1, ['option3' as 'option3' | 'option4']: 2 };
/* const v: {
    [x: string]: number;
    option1: number;
} */

This means that the compiler assumes v could have various property keys with number values, making it assignable to

{option1?: number, option2?: number}
:

myFunction(v); // okay

Refer to microsoft/TypeScript#13948 and microsoft/TypeScript#38663 for further details and authoritative information on this topic.

Access the code on 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

Using Javascript or Typescript constants along with WebPack being invoked twice

I am encountering an issue with my constants file: collections.ts import {Mongo} from 'meteor/mongo'; import {Chat, Message} from 'api/models'; export const Chats = new Mongo.Collection<Chat>('chats'); export const Me ...

Ways to access the new value of a cell in a Material UI Datagrid through the use of GridCellParams

When trying to access the newly modified value in a cell using the GridCellParams interface, I am faced with the issue that the 'value' property only provides me with the previous value of the cell. This asynchronous behavior is not ideal for my ...

Creating a dynamic image binding feature in Angular 8

I am working with an object array that requires me to dynamically add an image icon based on the type of credit card. Typescript file icon: any; savedCreditCard = [ { cardExpiryDateFormat: "05/xx", cardNumberLast: "00xx", cardId: "x ...

Separate Vue Js component data, methods, and props into individual TypeScript files

For my project, I am using Vue JS 2 along with TypeScript. In order to achieve this, I need to import data.ts, methods.ts, and props.ts into my customComponent.vue file: <!-- ////////////////////////////////////////////////////////////////////// --> ...

Simple method to determine if a variable belongs to an enumeration

Among the numerous discussions on this topic, none seem to focus on developing a versatile function. This function should take an enum and a variable as input, check if the variable is part of that enum, and update the variable type if it is. I have made ...

Configuring eslint-import-resolver-typescript in a multi-package repository

I'm currently working on implementing path-mapping within a monorepo structure. Despite having existing eslint-plugin-import rules in place, I am encountering an error stating "Unable to resolve path to module" for all mapped imports. app/ ├─ pack ...

"Encountering a problem with 'never' type in Angular 12 and Types

Currently, working with Angular 12 but encountering an issue with the following code snippet. this.recorder.ondataavailable = (event: { data: any; }) => { this.recordedChunks.push(event.data); }; Here is the error thrown by Typescript: Argument of ty ...

Transform ECMAScript Observable / Zen Observable into RXJS Observable

I currently have an ECMAScript Observable that is compliant with specifications, specifically sourced from the wonka library. I am facing challenges in converting this type of observable to an rxjs 6 observable. It appears that this conversion was possibl ...

Best practice for entering events in callback

Recently, I delved into Angular because I anticipate needing to use it down the line. My current focus is on studying components communication, particularly from child to parent. I came across various methods of achieving this. In each example, the ChildC ...

What is the correct way to write an asynchronous Express middleware function in Typescript?

Can anyone help me figure out how to correctly define a return value for an express middleware that utilizes async/await? I've been experimenting with different approaches but haven't found success yet. Additionally, I'm attempting to exten ...

Using Typescript to import functions

TLDR - I need help understanding the difference between these imports in ReactJs using Typescript: setState1: (numbers: number[]) => void, setState2: Function Hello everyone, I've encountered some strange behavior when importing functions with Typ ...

The assets path is the directory within the installed package that houses the main application files following the completion of a

I have a Vue.js UI component that is internally built using webpack. This reusable UI component library references its images as shown below: <img src="./assets/logo.png"/> <img src="./assets/edit-icon.svg"/>   <i ...

Having difficulties incorporating a separate library into an Angular project

My typescript library contains the following code, inspired by this singleton example code export class CodeLib { private static _instance: CodeLib; constructor() { } static get instance(): CodeLib { if(!this._instance){ ...

What could be causing the type errors I am encountering while trying to resolve this Promise within a generic function?

I am attempting to implement additional types within this WebSocket protocol: type Action = { action: "change-or-create-state"; response: string; } | { action: "get-state"; response: string | null; }; /** * map an action to its response ...

"Encountering a module not found issue while trying to

Attempting to test out 3 node modules locally by updating their source locations in the package.json files. The modules in question are sdk, ng-widget-lib, and frontend. ng-widget-lib relies on sdk, while frontend depends on ng-widget-lib. To locally build ...

I can't decide which one to choose, "ngx-bootstrap" or "@ng-bootstrap/ng-bootstrap."

Currently, I am in the process of deciding whether to use Bootstrap 4 with angular 4 for my upcoming project. However, I find myself torn between choosing npm install --save @ng-bootstrap/ng-bootstrap or npm install ngx-bootstrap --save. Could someone pl ...

Guide to making a TreeView in Angular 2 with Typescript

How can I implement a TreeView in Angular 2 using Typescript? I have searched on Google but have not found any working examples, etc. Could someone kindly provide me with an example to help me accomplish this task? ...

Increase the totalAmount by adding the product each time

Can someone help me understand why the totalAmount shows as 20 when I add a product? Also, why doesn't it increase when I try to increment it? Any insights would be appreciated. Thank you. ts.file productList = [ { id: 1, name: 'Louis ...

Running ngAfterViewInit() code in Angular should be done only after Inputs() have been initialized

Within a particular component, I have implemented some code in ngAfterViewInit: @Input public stringArray: string[]; public newArray: string[]; ngAfterViewInit() { this.newArray = this.stringArray.filter(x => x.includes('a')); } I placed ...

Error encountered: No matching overload found for MUI styled TypeScript

I am encountering an issue: No overload matches this call. Looking for a solution to fix this problem. I am attempting to design a customized button. While I have successfully created the button, I am facing the aforementioned error. Below is my code ...