The cause of Interface A improperly extending Interface B errors in Typescript

Why does extending an interface by adding more properties make it non-assignable to a function accepting the base interface type? Shouldn't the overriding interface always have the properties that the function expects from the Base interface type?

There are many questions on StackOverflow about this issue, but none of them explain why it happens, why it's supposed to be like this, or how to fix the error with the expected outcome.

Since 2017, there has been an open Github issue thread on the same topic - TS Proposal : "Interface incorrectly extends interface" - sub-interface method overload OR override ?

Where is my understanding of extended interfaces incorrect?

Please assist a newcomer TS developer!!! Thanks...

// ------------------------ Types Declaration ----------------

interface ServerRequest {
    url: string,
    method: string,
    body: string | undefined
}

interface ExtendedServerRequest extends ServerRequest {
    orignal_url: string | undefined
}

type FunctionOrignal = (req: ServerRequest)=> void
type FunctionOverridden = (req: ExtendedServerRequest)=> void

interface ShortHandOptions {
    onSend: FunctionOrignal
}

interface ExtendedShortHandOptions extends ShortHandOptions {
    onSend: FunctionOverridden
}

// ------------------------ Test ----------------------------

console.log('------------------------------------------------');

function test(opts: ShortHandOptions) {
    opts.onSend({
        url: 'https://httpbin.org/get',
        method: 'GET'
    } as ServerRequest);
}

var func1: FunctionOrignal = (req) => {
        console.log('FunctionOrignal', req.url);
    },
    func2: FunctionOverridden = (req) => {
        console.log('FunctionOverridden', req.orignal_url);
    };

test({ onSend: func1 } as ShortHandOptions);

test({ onSend: func2 } as ExtendedShortHandOptions);

This results in:-

Interface 'ExtendedShortHandOptions' incorrectly extends interface 'ShortHandOptions'.
  Types of property 'onSend' are incompatible.
    Type 'FunctionOverridden' is not assignable to type 'FunctionOrignal'.
      Types of parameters 'req' and 'req' are incompatible.
        Property 'orignal_url' is missing in type 'ServerRequest' but required in type 'ExtendedServerRequest'.

This should work as long as test function calls onSend with an argument of type ShortHandOptions, i.e. an argument with at least the following properties { url, method, body }.

Answer №1

Your demonstration is nearly accurate. When you input ExtendedServerRequest as

orignal_url?: string

instead of

orignal_url: string | undefined

everything should function as expected. Playground Connection

Reasoning

According to the TS compiler, there exists a distinction between defining a property as optional using ? or declaring a necessary property that may also be undefined, which you have done.

Because orignal_url can be undefined but is compulsory, you are unable to convert ShortHandOptions into ExtendedShortHandOptions as depicted in your scenario.

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

Is Axios the sole option for API calls when utilizing Next.js with SSG and SSR?

Can someone clarify the best practice for data fetching in Next.js? Should we avoid using axios or other methods in our functional components, and instead rely on SSG/SSR functions? I'm new to Next.js and seeking guidance. ...

RXJS: Introducing a functionality in Observable for deferred execution of a function upon subscription

Implementing a Custom Function in Observable for Subscribers (defer) I have created an Observable using event streams, specifically Bluetooth notifications. My goal is to execute a function (startNotifictions) only when the Observable has a subscriber. ...

Gain access to JSON information and store it in the datasource variable using the Kendo datasource function

Within my asp.net project, I have utilized the following approach to extract Json data from a js file: var ds = new kendo.data.DataSource({ transport: { read: { url: "http://localhost:2544/JS/emp ...

How to prevent duplicate database entries in Angular forms?

Currently, I am working on a project using Angular and TypeScript. The goal is to retrieve a list of users from an API and allow for the addition of new users. However, I am struggling with determining how to verify if a user with a specific name already e ...

Error occurred while trying to parse JSON due to an abrupt ending

While attempting to reinstall one of my old vue projects on my new computer (running Windows 10) using npm, I encountered the following error: npm ERR! Unexpected end of JSON input while parsing near '...n":"0.8.1","devDepend' ...

Creating a fresh array by applying a filter and assigning keys

I am facing an issue with my array structure, it looks like this, [ [ "Show/Hide", "P000", "MAX-CT05 FVM2-", "S", 1532, -9.5929406005, null, null, ...

Deliver router services for central Angular 2 elements

I am working on an ng2 app where I have the app/app.module and core/core.module. In the core modules, there are some modules that are used at the app top level and only once as mentioned in the official documentation. However, one of these modules requires ...

"Ensuring the right data type is selected for the onChange event

In my code, I have a simple select component set up like this. import { Controller } from "react-hook-form"; import Select, { StylesConfig } from "react-select"; //.. const [universe, setUniverse] = useState<SetStateAction<TOptio ...

What is the best way to separate a string using a comma as a delimiter and transform it into a string that resembles an array with individual string elements

I am in search of a way to transform a string, such as: "one, two, three, four" into a string like: "["one", "two", "three", "four"]" I have been attempting to devise a solution that addresses most scenarios, but so far, I have not been successful. The ap ...

Clearing a textarea in jQuery

I'm experiencing an issue that I can't seem to resolve on my own. Any assistance would be greatly appreciated. My function designed to clear a textbox upon click doesn't seem to be working correctly: $(function() { $('textarea#co ...

Attempting to retrieve a stream buffer from a function

I am currently working on creating a zip file that contains a CSV file and returning it as a buffer from a function. Below is the code snippet I have implemented: const archiver = require('archiver'); const streamBuffers = require("stream-bu ...

Implementing user authentication in node.js with passport

Having trouble with a basic login system using passport. I keep getting an error when logging in with the correct credentials: Error: Express 500 TypeError - Cannot read property 'passport' of undefined Oddly enough, everything works fine when ...

What is the best way to incorporate sturdy data types into the alternative function for this switch statement

const switchcase = (value, cases, defaultCase) => { const valueString = String(value); const result = Object.keys(cases).includes(valueString) ? cases[valueString] : defaultCase; return typeof result === 'function' ? result() : r ...

What does the client perceive or not perceive? Node.js, JavaScript, MySQL

For a university project, I am tasked with creating a web application that is compatible with both desktop browsers and mobile devices. The technologies I will be using include HTML, CSS, JavaScript, Node.js, and MySQL. I have recently familiarized myself ...

TSLint in TypeScript showing unexpected results

In the process of developing a project using Angular, I recently made the switch from VS Code to WebStorm. Unfortunately, I'm encountering some difficulties that I can't seem to make sense of. To ensure everything is functioning correctly, I perf ...

unable to make a request to the express server with axios

I am in the process of developing a chat application similar to whatsapp. One of the key features I'm working on is that when a user clicks on another person's name, their chats will be displayed. However, currently, I'm facing an issue wher ...

Tips on working with an array received from a PHP script through AJAX

I've been stuck with this issue for the past few hours and I'm hoping to find a solution here. What I'm attempting to do is something like the following: PHP: $errorIds = array(); if(error happens){ array_push($errorIds, $user['user ...

Create an instance of a class from a group of subclasses, all the while retaining the ability to access static members in Types

I seem to have encountered a dilemma where I am looking to have both the static and abstract keywords used for a member of an abstract class in TypeScript, but it appears that this combination is not supported. The nearest workaround I could come up with ...

Dynamic table in Vue.js updates with saved data when button is clicked

I am looking for assistance on how to work with two or more parameters using Vue.js. I have a data-saving functionality where three inputs are used and the data is saved to a table upon button click. There is an $.ajax() function involved, but I need help ...

Shuffle the JSON data before displaying it

Just a heads up, the code you're about to see might make you cringe, but I'm doing my best with what I know. I've got a JSON file with a bunch of questions, here's what it looks like: { "questions": [ { "id": 1 ...