What causes the inconsistency in TypeScript's structure typing?

It is well-known that TypeScript applies structure typing, as demonstrated in the following example:

interface Vector {
   x: number;
   y: number;
}

interface NamedVector {
   x: number;
   y: number;
   name: string;
}

function calculateLength(v: Vector) {
   return Math.sqrt(v.x * v.x + v.y * v.y);
}

const v: NamedVector = { x: 3, y: 4, name: 'zee' };
calculateLength(v);   // compiles without errors, result is 5

This allows calculateLength to be called with a NamedVector because their structures are compatible.

However, when it comes to assignment, structure typing is not used anymore:

const v: Vector = { x: 3, y: 4, name: 'Zee' };  // compile error, 'name' does not exist in type 'Vector'

Based on the definition of structure typing, { x: 3, y: 4, name: 'Zee' } should also be compatible with Vector, so why doesn't structure typing work in this case?

Furthermore, what Utility Types can be used to describe a type that must contain both x and y fields along with some other fields, in order to do something like:

const v: XXX<Vector> = { x: 3, y: 4, name: 'Zee' };

Answer №1

It's hard to imagine a practical scenario where this approach would be useful, but the most straightforward way to down-cast is simply by casting the object.

const obj = { x: 3, y: 4, name: 'John' } as Object;

However, keep in mind that you won't be able to access obj.name, making this exercise seemingly pointless.

Answer №2

In response to your second inquiry

interface Vector {
   x: number;
   y: number;
}
const v: Vector & {[x:string]: any}= { x: 3, y: 4, name: 'Zee' }; 

Play around with Typescript here

The initial question lacks sufficient detail for a clear answer, in my view.

Answer №3

It is recommended to avoid using excess properties in Object literals. Instead, consider utilizing Custom Generics to prevent the use of excess properties.

interface Vector {
   x: number;
   y: number;
}

interface NamedVector {
   x: number;
   y: number;
   name: string;
}

function calculateLength(v: Vector) {
   return Math.sqrt(v.x * v.x + v.y * v.y);
}

type Optional<T, N extends keyof T> = Partial<Pick<T, N>> & Omit<T, N>;

const v: Optional<NamedVector, "name"> = { x: 3, y: 4, name: 'Zee' };
calculateLength(v);

ref: https://www.typescriptlang.org/docs/handbook/type-compatibility.html#starting-out

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

constructing a nested container using XMLHttpRequest

I am working on creating a nested div-container structure using AJAX and adding the text "Hello World" to the inner container. The outer container serves as a holder for the inner container in this case. Below is the code I have written: index.html: ...

What is the reason behind permitting void functions in the left part of an assignment in Typescript?

Take a look at this Typescript snippet: let action = function (): void { //perform actions }; let result = action(); What makes it suitable for the TypeScript compiler? ...

foreverjs neglects to log the child process's console.log output to any log files

I currently have a nodejs server running that fetches data using the setInterval function every x seconds. Here is a snippet of that part of the app: startPolling () { debug('Snmp poller started'); timers.setInterval( this.poll( ...

What are the drawbacks of introducing a dependency within the constructor?

I'm struggling to understand why breaking the rules is considered bad. import {DepClass} from './di-import' // <- some dependency imports here class DI1 { dep1: DepClass constructor(){ this.dep1 = new DepClass() // ...

Tips for triggering functions when a user closes the browser or tab in Angular 9

I've exhausted all my research efforts in trying to find a solution that actually works. The problem I am facing is getting two methods from two different services to run when the browser or tab is closed. I attempted using the fetch API, which worke ...

Tips for transferring a variable from a webpage's JavaScript to Node.js

Having an issue with transferring a Javascript variable to node js for JSON file storage. The data doesn't seem to be writing to the file, possibly due to an error in the AJAX Post request or the node JS routing. The javascript is executed on an HTML ...

Switch up the current Slick Carousel display by utilizing a div element

We have implemented the slick carousel to show only one slide at a time within the <div class='item__wrapper'>. Beneath this are three items, and we want the slick carousel to update when any of these items are clicked. Issues Using item ...

Tips for effectively generating a JSON object array in Typescript

Currently, I'm attempting to construct an array of JSON objects using TypeScript. Here is my current method: const queryMutations: any = _.uniq(_.map(mutationData.result, function (mutation: Mutation) { if (mutation && mutation.gene) { co ...

Guide to creating a Unit Test for an Angular Component with a TemplateRef as an Input

Looking to create unit tests for an Angular component that can toggle the visibility of contents passed as input. These inputs are expected to be defined as TemplateRef. my-component.component.ts @Component({ selector: "my-component", templateUrl ...

What is the best way to utilize the .done() callback in order to execute a function when new data is loaded upon request?

I have a web page that pulls data from a JSON feed, and there's also a button to load more content from the feed when clicked. I want to add additional elements inside the page for each item in the feed. I've managed to create a function that doe ...

The ajax method for loading an xml file results in displaying the undefined message

When attempting to fetch content from an xml file using ajax, the page initially displays "undefined". However, upon refreshing the page, the content loads successfully. Take a look at my code snippet below: $.ajax({ type: "GET", url: "xm ...

Display a list of items in Angular using ng-repeat, and allow the full description to appear in full width

<div ng-controller = "MyController"> <ul class="items" > <div ng-repeat="item in colors" ng-class="{active:isActive(item)}" ng-click="select(item); whattoshow=!whattoshow"> <li class="col-md-3 col-sm-3 col-lg-3 co ...

Step-by-step guide to implementing a datepicker textfield with Vuetify 3

I'm currently exploring Vuetify 3 and aiming to implement a textfield that serves as a datepicker. For reference, you can find a similar example in the Vuetify 2 documentation here. Unfortunately, the Vuetify 3 docs do not yet include an example like ...

Ensure menu options are aligned to the right using material-ui

My material-ui menu currently has the following setup: <span> <Link to="/issues"> <Button style={isActive(history, "/issues")}>Issues </Button> </Link> <Link to="/users"> <Button style={isActive(his ...

Removing characters from a string with regular expressions

I need to eliminate instances of << any words #_ from the given text. stringVal = "<<Start words#_ I <<love#_ kind <<man>>, <<john#_ <<kind man>> is really <<great>> <<end words#_ "; The d ...

How to eliminate the button from Google Maps API using JavaScript

I am trying to implement a specific functionality on my map. When the user drags the map, I want a button named 'Search in this area' to appear. Once the user clicks on the button, it should disappear so that the search can't be performed ag ...

Express and Firebase Function: Headers cannot be set once they have already been sent

My experience has been mainly with the Hapi framework for developing RESTful APIs. However, for my current project, I decided to use Express and I'm encountering some confusion regarding the issues that are arising. While testing the POST endpoint us ...

The Link Breaks the Overlay Hover Effect

Currently, the code functions as intended when you hover over or touch the thumbnail, an overlay will appear. The issue lies in the fact that to navigate to a specific URL, you have to click directly on the text. The overlay itself is not clickable and ca ...

Create a JavaScript code snippet that replaces the innerHTML of the function document.getElementById with

In my limited knowledge of JavaScript, I have come across an issue with the following code: function example() { document.getElementById("example").innerHTML = "<script>document.write(example)</script>"; } Unfortunately, this code doesn&ap ...

I'm experiencing difficulty in scrolling on my Nextjs web application

Currently, I am facing an issue with my portfolio webpage which is divided into 3 main components - Hero, About, and Portfolio. The layout structure is as follows: export default function RootLayout({ children, }: { children: React.ReactNode }) { ret ...