TypeScript treats merged interfaces as being of the type never

I combined several interfaces to create a new type. But for some reason, TypeScript is treating my type as never. Can you help me figure out why?

type OrganizationAccount = Account & DetailedAccount & AccountSelection;

interface Account {
  name: string;
  created_on: string;
}

interface DetailedAccount {
  account_type: string;
  status: string;
}

interface AccountSelection {
  isSelected?: boolean;
}

Initially, my API request only returns the basic Account properties like name and created_on. When the user clicks a button to fetch more details, another request is made which adds the extra DetailedAccount properties to the account object.

function getAccountDetails(account: OrganizationAccount) {
  setOrganizationAccounts((prevState: OrganizationAccount[]) => {
    return prevState.map(organizationAccount => {
      return organizationAccount.name === account.name
        ? {
          ...organizationAccount,
          ...accountDetailsRes,
          }
        : organizationAccount;
      });
    });
  });
}

Later in the code, I check for the presence of account_type to display different results. However, TypeScript seems to mistakenly infer that the account variable is of type never.

function accountType(account: OrganizationAccount) {
  if (!('account_type' in account)) { // Here account === OrganizationAccount
    console.log('account', account);  // Here account === never

    return 'Loading...';
  }

  return account.account_type;
}

Answer №1

if (!('account_type' in account)) {
will always return false when working with TypeScript, as the property account_type is required in the OrganizationAccount interface.

An updated version of OrganizationAccount could be:

type OrganizationAccount = (Account | DetailedAccount) & AccountSelection;

interface Account {
  name: string;
  created_on: string;
}

interface DetailedAccount extends Account {
  account_type: string;
  status: string;
}

interface AccountSelection {
  isSelected?: boolean;
}

For a practical example:

type OrganizationAccount = (Account | DetailedAccount) & AccountSelection;

interface Account {
  name: string;
  created_on: string;
}

interface DetailedAccount {
  account_type: string;
  status: string;
}

interface AccountSelection {
  isSelected?: boolean;
}

let a: OrganizationAccount = {
  name: 'a',
  created_on: 'string',
  isSelected: false
};
a.name = 'a';
a.created_on = 'string';
a.isSelected = true;

let b: OrganizationAccount = {
  name: 'b',
  created_on: 'string',
  isSelected: false,
  account_type: 'type',
  status: 'string'
};
b.name = 'b';
b.created_on = 'string';
b.isSelected = true;
b.account_type = 'type';
b.status = 'string';

function f(account: OrganizationAccount) {
  console.log(account.name);
  if ('account_type' in account) {
    console.log(account.account_type);
  }
}

f(a);
f(b);

Try it on TypeScript playground

Answer №2

Here's a suggestion for you:

const object1 = {
   property1: "Hello",
   property2: true,
};

const object2 = {
    property3: "World",
    property4: false,
};
const combinedObjects = { ...object1, ...object2 };

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

In TypeScript, develop a specialized Unwrap<T> utility type

After successfully creating a helper type to unwrap the inner type of an Observable<T>, I began wondering how to make this type completely generic. I wanted it to apply to any type, not just Observable, essentially creating Unwrap<T>. Here is ...

A specialized <T> interface, now enhanced with additional functionalities

Looking to create a generic type (with parameter T) that exhibits the following behavior: If K represents a key of T, allow the value type to be either T[K] | ((params?: Partial<T>) => string) If K is not a key of T, allow the value type to be ( ...

What are the steps to manually activate input validation in Angular 2?

Having two inputs is the scenario here: The first input undergoes custom validator application The second input has a dynamic and editable value utilized in the custom validator If the custom validator is applied on the first input, then focus shifts to ...

Having trouble with importing a TypeScript class: encountering a "cannot resolve" error message

Could you lend me your expertise? I'm puzzled by this issue that seems to be quite simple and straightforward: export class Rectangle { height: number = 0 width: number = 0 constructor(height: number, width: number) { this. ...

Angular is putting the page on ice - all clicks are officially off limits

When making an HTTP request to the backend in my project, I need the ability to sort of "freeze" the screen until the request is complete. Specifically, I want to prevent users from being able to interact with certain elements on the page, such as a butt ...

Utilize the data structures and variables from one module to enhance the functionality

Currently, I am utilizing Babylonjs with Rollupjs in conjunction with typescript. https://i.sstatic.net/2L3bY.png When importing Babylonjs like so: import { ArcRotateCamera, Engine, SceneLoader, Vector3 } from "babylonjs"; I am able to access all the t ...

utilizing props to create a navigational link

How can I display a tsx component on a new tab and pass props into the new page? Essentially, I'm looking for the equivalent of this Flutter code: Navigator.push( context, MaterialPageRoute(builder: (context) => Page({title: example, desc: ...

Using Vue: How to utilize v-slot variables in JavaScript

Can the values of the v-slot of a component be accessed in the script? For instance, consider the following template: <cron-core v-model="value" :periods="periods" :format="format" v-slot="{fields, period, error}"> {{period}} <div v-for="fiel ...

Palantir Forge: Enhancing Column Values with Typescript Functions

I am seeking assistance with a TypeScript function related to ontology objects. I want to develop a TypeScript program that accepts a dataframe as input. The objective is to nullify the values in other columns when a value from a row in a particular column ...

Encountering an issue with Typescript Vue class-based components in Laravel Mix: issue arises when attempting to set property 'render' on an undefined object

I have been using Laravel Mix to compile my Vue components, incorporating TypeScript and class-based components. Each class is exported from the component, and every component is required by the context in the main application script. However, during rende ...

Having trouble sending an HTTP request to my .Net Core 2.1 web project

In my current project, I am working with Angular 6 and .Net Core 2.1. The Angular 6 code is in one project, while the .Net Core 2.1 controller methods for login authentication are in another project. I have noticed that both projects are using different lo ...

What is the best way to build a versatile typeExclude helper function that can handle a wide range of types and is

I am currently working on developing a dynamic function that can assess whether a particular element meets certain criteria. This project serves as an extension to the original discussion found in this question. One challenge I am facing is that the &apos ...

Implementing Caching in Angular 5 Services

Searching for the best way to implement Angular services has led me here. The Service: const url = 'http://127.0.0.1:8000/api/brands/' @Injectable() export class BrandService { private brands:Observable<Array<Brand>>; constru ...

Error in Typescript cloud function: response object is not callable

My cloud function is structured like this: // const {onSchedule} = require("firebase-functions/v2/scheduler"); // The Cloud Functions for Firebase SDK to set up triggers and logging. import * as logger from "firebase-functions/logger&quo ...

After upgrading Expo, the React Native Auth Session ceased to function

During my use of Expo SDK 48, my app successfully implemented Google and Facebook authentication with a web browser-based authentication method. Functional code: type AuthResponse = AuthSession.AuthSessionResult & { params: { access_token ...

Steps for creating a read-only Material-UI input text field in Angular 12

I'm looking to create a read-only text field using Material-UI that cannot be edited. I attempted to achieve this by disabling it in the .ts file of the component: this.firstFormGroup.controls['gauthan_nirmit'].disable(); However, when I m ...

Interface circular dependency is a phenomenon where two or more interfaces

In my MongoDB setup, I have created an interface that defines a schema using mongoose as an ODM. import mongoose, { model, Schema, Model, Document } from "mongoose"; import { IUser } from "./user"; import { IPost } from "./posts&q ...

The mock function will only be triggered if it is placed at the beginning of the file

In an attempt to simulate a React function component for the purpose of validating the properties passed to it, I encountered an interesting difference in behavior. When the mock is placed at the top of the file, everything works as expected: const mockTra ...

Crafting a recursive Typescript Immutable.js Record through typing

I am currently working on representing a tree-like data structure using immutable js and typescript. At the moment, I am utilizing regular vanilla js objects to depict the nodes within the tree. Below is the type signature. type NodeType = { value: str ...

Simulating service calls in Jest Tests for StencilJs

When testing my StencilJs application with Jest, I encountered an issue with mocking a service class method used in a component. The service class has only one function that prints text: The Component class: import {sayHello} from './helloworld-servi ...