Assigning a generic object to a Partial type

Recently I've been diving back into TypeScript, but I've hit a roadblock with this particular issue.

export class CrossBrowserStorage<T> {
  getValue<P extends keyof T>(
    key: P,
    defaultValue: T[P]
  ): Observable<T[P]> {
    return this.getValues({ [key]: defaultValue }).pipe(map(values => values[key]));
                      ----^ TS2345: Argument of type '{ [x: string]: T[P]; }' is not assignable 
                            to parameter of type 'Partial '
  }

  getValues(keys: Partial<T>): Observable<Partial<T>> {
    return from(browser.storage.sync.get(keys) as Promise<Partial<T>>);
  }
}

TS2345: Argument of type '{ [x: string]: T[P]; }' is not assignable to parameter of type 'Partial'

I'm struggling to figure out how to resolve this issue while still ensuring the correct typings are maintained.

Answer №1

The compiler is unable to verify this scenario for you, but you can use a type assertion as a workaround:

class Class<T> {
    f<K extends keyof T>(k: K, v: T[K]) {
        const badPartial: Partial<T> = { [k]: v }; // error!
        const goodPartial: Partial<T> = { [k]: v } as Pick<T, K> & Partial<T>; // okay
    }
}

This is one solution to the issue at hand. The compiler faces two main obstacles in dealing with cases like these.


The first challenge arises when the key of a computed property is not statically known or unique:

const k1 = "a";
const o1 = { [k1]: 123 }; 
// const o1: {[k1]: number};
o1.a; // okay
o1.b; // error

If the key type is generic or a union of string literals, TypeScript widens it to string, resulting in unexpected behavior:

const k2 = Math.random() < 0.5 ? "a" : "z";
const o2 = { [k2]: 123 };
// const o2: {[x: string]:number};
o2.a; // no error, might not exist
o2.b; // no error, definitely doesn't exist

function foo<K extends string>(k3: K) {
    const o3 = { [k3]: 123 };
    // const o3: {[x: string]:number};
    o3.a; // no error, probably doesn't exist
}

Another stumbling block relates to associative types and higher-order type manipulation, where the compiler struggles to infer compatibility between various types. This leads to the need for manual intervention through type assertions. For more details on this aspect, refer to the open issuehere.


Due to these limitations in TypeScript's inference capabilities, relying solely on the compiler to verify certain assignments feasibly may not yield desirable outcomes. Hence, utilizing type assertions remains a practical approach to address such scenarios effectively.

Hopefully, the provided insights will prove valuable. Best of luck!

Playground link to 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

Preventing specific directories from being imported in a Typescript project

I am intrigued by the idea of restricting files within a specific scope from importing files from another scope. Let's consider this example: Imagine we have the following project structure: project/ ├── node_modules/ ├── test/ ├── ...

The ngAfterViewInit lifecycle hook does not get triggered when placed within ng-content

The ngAfterViewInit lifecycle hook isn't triggered for a Component that is transcluded into another component using <ng-content>, as shown below: <app-container [showContent]="showContentContainer"> <app-input></app-input> ...

The Angular Ivy strictTemplates error message states that the type 'Event' cannot be assigned to the type 'InputEvent' parameter

I'm feeling lost trying to figure out what's wrong with this code snippet: <input #quantity type="number" matInput formControlName="quantity" (input)="onQuantity($event, i)" placeholder="Quantity"/> onQuantity(event: InputEvent, i: number ...

Understanding how to infer the type of a function when it is passed as an argument

Looking at the images below, I am facing an issue with my function that accepts options in the form of an object where one of the arguments is a transform function. The problem is that while the type of the response argument is correctly inferred for the e ...

Error: Name 'AudioDecoder' could not be located

In my current project using React and TypeScript with Visual Studio Code 1.69.2 and Node 16.15.1, I encountered an issue. I am attempting to create a new AudioDecoder object, but I keep getting an error message stating "Cannot find name 'AudioDecoder ...

Tips for eliminating inline CSS usage in React

Is it possible to avoid using inline CSS in React when styling an element like this? const dimensionStyles = { width: 10, height: 20 }; <div className="point-class" style={{ width: dimensionStyles.width + "px", height: ...

Encountering a non-constructor error while trying to import packages in React Typescript

I am currently working on a project that utilizes React with Typescript. While attempting to import a package, I encountered an error stating that the package lacks a constructor when I run the file. This issue seems to be prevalent in various packages, a ...

The variable X has been defined, but it's never actually utilized. Despite declaring it, I have not accessed its

I have encountered warnings in VSCode while using certain properties in my Angular component. The warnings state: '_id' is declared but its value is never read.ts(6133) (property) ItemEditComponent._id: number | undefined '_isModeEdit' ...

Switch up your component button in Angular across various pages

I've created a new feature within a component that includes a toolbar with multiple buttons. Is there a way to customize these buttons for different pages where the component is used? Component name <app-toolbar></app-toolbar> Component ...

Encountering issues with Phaser Sprite body when receiving undefined input

I am having trouble with flicking when I click the mouse. The variable on input.on is returning undefined when I click the mouse. Here is a code snippet that explains my issue. Phaser is a new concept to me. w : number; h : number; velocity:n ...

Are getter and setter pairs permitted to override properties in the base class of JavaScript/TypeScript?

Recently, there has been an update in TypeScript that triggers a compilation error when attempting to override a property in the base class with a getter/setter pair. This issue arises from property access augmentation: class BaseClass { prop : ...

Converting JSON data into TypeScript interface objects within an Angular 2 environment

I have a JSON dataset with the following structure: { "timestamp": 1467471622, "base": "USD", "rates": { "AED": 3.673027, "AFN": 68.475, "ALL": 123.095199, "AMD": 476.8075, "ANG": 1.78385, "AOA": 165.846832, "ARS": 15.05 ...

Encountering issues while attempting to transmit several files to backend in React/NestJS resulting in a BAD REQUEST error

My goal is to allow users to upload both their CV and image at the same time as a feature. However, every time I attempt to send both files simultaneously to the backend, I encounter a Bad Request error 400. I have made various attempts to troubleshoot th ...

Encountering an error in Angular where the property does not exist in type

Struggling to create a collapsible menu within my header component in an Angular project, I've hit a snag with proper JSON formatting. The error message that keeps popping up reads: Error: src/app/components/header/header.component.html:48:49 - error ...

Implementing a NestJs application on a microcomputer like a Raspberry Pi or equivalent device

I'm facing a challenge in trying to find a solution for what seems like a simple task. I am aware that using the Nest CLI, I can utilize the command "nest build" to generate a dist folder containing the production files of my project. However, when I ...

What is the best ECMAScript version to select for implementing the TypeScript compiler in an Electron application?

In my Electron 5.0.6 project, I currently have es3 as the default target in my tsconfig.json file. However, I received an error message indicating that I need to upgrade to at least es6 to utilize getter/setter functionality in TypeScript. I am now contem ...

The index type '{id:number, name:string}' is not compatible for use

I am attempting to generate mock data using a custom model type that I have created. Model export class CategoryModel { /** * Properties */ public id : number; public name : string; /** * Getters */ get Id():number{ return this.id; ...

"Error occurs as a result of an unspecified attribute in the map

Hello, I am currently traversing a tree structure recursively. To handle undefined nodes in the tree, I have implemented guards to prevent any failures. However, during the mapping of children nodes, I encountered the following error: Error Output Adri ...

Exploring the concept of union return types in TypeScript

Hello, I am facing an issue while trying to incorporate TypeScript in a way that may not be its intended use. I have created a custom hook called useGet in React which can return one of the following types: type Response<T> = [T, false, false] | [nul ...

Alter the class based on the incoming string from the rxjs stream

I have a stream that outputs strings, and based on these strings I want to apply certain classes to a specific tag: If the string is "ok", add class "fa-check" If the string is "loading", add classes "fa-spin" and "fa-spinner" If the string is "error", a ...