Type 'Partial' cannot be assigned a value when combining interfaces with generic types

Consider the following scenario:

class Table<ValuesType extends DefaultTableValues = DefaultTableValues>{
    public values: ValuesType;
    constructor(initialValues:ValuesType) {
        this.values=initialValues;
    }

    public set(newValues:Partial<ValuesType>){
        this.values={
            ...this.values,
            ...newValues
        }
    }
}

class User<MoreValues extends UserValues = UserValues> extends Table<MoreValues>{
    constructor(values:MoreValues) {
        super(values);

        this.set({avatar:'some-string'});
        //ERROR - Argument of type {avatar:'some-string'} is not assignable to type Partial
    }
}
interface DefaultTableValues{
    id:string;
}
interface UserValues extends DefaultTableValues{
    avatar:string;
    username:string;
}

An error occurs when using this.set with the message:

Argument of type {avatar:'some-string'} is not assignable to type Partial

Changing

class User<MoreValues extends UserValues = UserValues> extends Table<MoreValues>
to
class User extends Table<UserValues>
solves the issue, but it limits passing specific User types and extending the User class.

Is it expected for MoreValues to always include the avatar:string property as it extends UserValues?

This situation seems related to this question on Stack Overflow, but finding a solution for my case remains elusive.

Answer â„–1

The issue you are pointing out is indeed similar to the one mentioned in the linked question. The accepted answer from that question states:

Subtyping goes beyond just adding extra properties—it can involve narrowing down the range of acceptable values for those properties.

To illustrate, consider the following interface:

interface RestrictedValues extends UserValues {
    avatar: "nonexistent"
}

This interface extends UserValues, making it compatible with MoreValues. However, the avatar property within this interface is limited to only having the value nonexistent. Therefore, when using the Partial<> type as the first argument for the set() function, it should specifically allow the value nonexistent, not any arbitrary string as implied by UserValues. For example, consider the code snippet below:

class User<MoreValues extends UserValues = UserValues> extends Table<MoreValues>{
    constructor(values: MoreValues) {
        super(values);

        const thing1: RestrictedValues = { avatar: "nonexistent", id: "", username: "" };
        const thing2: MoreValues = thing1;
    }
}

In this scenario, thing1 cannot be directly assigned to

thing2</code because there is no guarantee that <code>MoreValues
will always be instantiated with a value such as { avatar: "" }. If MoreValues allows other subtypes besides RestrictedValues, TypeScript generates the error:

Type 'RestrictedValues' is not assignable to type 'MoreValues'.
  'RestrictedValues' meets the constraints of 'MoreValues', but 'MoreValues' may receive a different subtype than 'UserValues'.

A simpler demonstration of this concept involving boolean values is presented in this answer, which provides further clarity on this matter.

The error indicates that your Generic Type P cannot be assigned a value of {} because P may adhere to a more specific or restricted type that conflicts with the default value.

This means that an empty object {} may not satisfy all the potential types used by Generic Type P.

Let's consider a simpler example focusing solely on boolean values for better comprehension:

interface OnlyBoolIdentityInterface<T> {
  (arg: T): T;
}

function onlyBoolGeneric<T extends boolean>(arg: T = false): T {
  return arg;
}

If we define a type more nuanced than simply a boolean, for instance:

type TrueType = true;

and specialize the function OnlyBoolIdentityInterface to accept only true values like so:

const onlyTrueIdentity: OnlyBoolIdentityInterface<TrueType> = onlyBoolGeneric;

Even though TrueType adheres to the constraint enforced by T extends boolean, the default value arg: T = false does not align with TrueType.

This discrepancy is what the error message aims to convey.

So how can you rectify such errors? Here are some approaches:

  1. Omit the default value
  2. Ensure that T encompasses the specialized type of the default parameter (in this case, false)
  3. Directly align T with parameters utilizing default values

For additional insights into this error message, refer to the corresponding issue: https://github.com/Microsoft/TypeScript/issues/29049.

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

Exporting key/value objects with React components as values in Typescript

I have a .tsx file where I need to export an object containing key/value pairs. Each value is going to be a React component used in another file. While I will have multiple key/value pairs, I'm focusing on just one at the moment. object.tsx import { ...

Mastering ngClass for validation in Angular 2: Step-by-step guide

I am facing an issue with a form I have created where I applied ngclass to display an error when the form value is missing. However, the error is showing up when the form is initially loaded. It seems that by default, my input tag is invalid when the form ...

Analyzing arrays and object key/value pairs based on a specific value in javascript

I want to create a new object with key/value pairs. The new object should include values from an existing key/value object as well as unique values from an array. Here is the array: [{ name: "Computer", name: "Car", name: "House&q ...

What is the best way to adjust the Material Drawer width in Reactjs to match the width of its children?

Currently, I am utilizing the Material-ui Drawer component to toggle the display of content on the right side of the screen. The functionality I am aiming for is that when the Drawer opens, it will shrink the existing content on the right without any overl ...

Tips on exporting a basic TypeScript class in an Angular 4 module

I am facing a challenge with packaging a TypeScript class as part of an Angular module for exporting it as a library using ng-packagr. For instance, here is my class definition - export class Params { language: string ; country: string ; var ...

Exploring ways to simulate an event object in React/Typescript testing using Jest

I need to verify that the console.log function is triggered when the user hits the Enter key on an interactive HTMLElement. I've attempted to simulate an event object for the function below in Jest with Typescript, but it's not working as expecte ...

Accessing nested objects within an array using lodash in typescript

After analyzing the structure of my data, I found it to be in this format: {property: ["a","b"], value : "somevalue" , comparison : "somecomparison"} I am looking for a way to transform it into a nested object like so: { "properties": { "a": { ...

Employ material-ui default prop conditionally

I am implementing a StepLabel component in material ui. Depending on the props passed to the parent, I may need to make changes to the icon property of the StepLabel: interface Props { customClasses?: ClassNameMap; customIcon?: ReactNode; } const MySt ...

What is the best way to include type within a nested object?

How should I properly define types for a nested object structured like the example below? const theme: DefaultTheme = { color: { primary: '#5039E7', secondary: '#372E4B', heading: '#4D5062', }, ...

Angular2 Eclipse: Eclipse Oxygen's HTML editor detects TypeScript errors in real-time

After installing the Eclipse Oxygen plugin for Angular2, I created a project using the Angular CLI and opened it in Eclipse. However, when trying to convert the project to an Angular project, I couldn't find the option under configuration. Instead, th ...

Leverage the generic parameter type inferred from one function to dynamically type other functions

I am in the process of developing an API for displaying a schema graph. Here is a simplified version of what it entails: interface Node { name: string; } type NodeNames<T extends Node[]> = T[number]["name"]; // Union of all node names as strings ...

Revamp your search experience with Algolia's Angular Instant Search: Design a personalized search box template

Custom Search Box Request: My goal is to implement an autosuggest search box using Algolia Angular instant search with an Angular Material design. To achieve this, I am planning to customize the search box component by replacing the standard <ais-sea ...

Creating a type that can be used with a generic type T along with an array of the same generic type T

I am experimenting with TypeScript for this project type ArrayOrSingleType<T> = T | T[]; interface TestType<T> { a: ArrayOrSingleType<T>; b: (v: ArrayOrSingleType<T>) => void; } const testVariable: TestType<number&g ...

Leverage both props and destructuring in your Typescript + React projects for maximum efficiency!

Is it possible to use both destructuring and props in React? For instance, can I have specific inputs like name and age that are directly accessed through destructuring, while also accessing additional inputs via props? Example The desired outcome would ...

typescript exploring the versatility of dynamic types and generics

Understanding TypeScript dynamic and generic types can be challenging for me. The goal is to create a function that generates an object with a specific type, where some properties of the object must match the parameters provided to the function. Essentia ...

Saving a JSON object to multiple JSON objects in TypeScript - The ultimate guide

Currently, I am receiving a JSON object named formDoc containing data from the backend. { "components": [ { "label": "Textfield1", "type": "textfield", "key": "textfield1", ...

Adding a fresh element to an array in Angular 4 using an observable

I am currently working on a page that showcases a list of locations, with the ability to click on each location and display the corresponding assets. Here is how I have structured the template: <li *ngFor="let location of locations" (click)="se ...

Resolving Unhandled Runtime Errors When Using Components with Dynamic API Calls in NextJS: A Guide to Fixing the Issue

As someone who is new to web development, I am currently working on a web app that makes use of the IGDB API (). The concept behind this website is allowing users to listen to game soundtracks and guess which game they belong to. For selecting a game, the ...

Angular displays a datalist input as "[object Object]" once a value has been selected

In my form, I have the following section: <div formArrayName="studentPublishing" *ngFor="let all of getstudentPublishing().controls; index as i"> <div class="form-group data"> <input type="text& ...

Error: The checkbox was clicked, but an undefined property (includes) cannot be read

Link to live project preview on CodeSandbox Visit the product page with checkbox I have developed a code snippet that allows users to filter products by checking a box labeled "Show Consignment Products Only", displaying only those products with the term ...