Are indexed properties constraints in Typescript only working with raw types and not with object literals?

After defining this interface:

interface Thing1 {
    [key: string]: string;
    x: number;
}

During compilation in Typescript, an error is thrown stating "TS2411: Property 'x' of type number is not assignable to string index type 'string'."

While this error seems reasonable, when using an object literal as the indexed type value like:

interface Foo {}
interface Thing2 {
    [key: string]: Foo;
    foo: number;
}

Surprisingly, there is no error reported, even though number and Foo are different types.

Do you have any insights into why this inconsistency occurs?

Note: This was tested on Typescript 2.1.5

Answer №1

The reason for this behavior is the way type compatibility functions in TypeScript:

Type compatibility in TypeScript relies on structural subtyping, which compares types based on their members rather than their names. This differs from nominal typing.

For example, the following code snippet is valid:

interface Foo {}
let f: Foo = 3;

This is because every property in {} has a corresponding property with the same name and type in Number.

However, the following code will result in an error:

interface Foo {}
let f: Foo = 3;
let b: number = f;

The compiler flag an issue at let b: number = f;:

Type 'Foo' cannot be assigned to type 'number';

Once again, referring to the documentation:

TypeScript's structural type system was developed to align with the typical coding practices of JavaScript. Given that JavaScript often uses anonymous objects like function expressions and object literals, it makes more sense to represent relationships found in JavaScript libraries using a structural type system as opposed to a nominal one.

Answer №2

When dealing with empty interfaces in Typescript, it's important to note that they are compatible with simple types such as numbers and strings. For example, you can assign a number to a variable declared as an interface like this:

let x: Bar = 5;

This means that in some cases, Typescript will still consider the interface compatible with the assigned type. However, if the interface includes an index signature (like in Thing1), all members must adhere to the specified type (in this case, string).

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

Encountering a Issue with Http module in Angular

When attempting to call my API using HttpModule, an error is being thrown upon starting the server (please refer to the screenshot). Error Image The error arises when I try to make a call to the API from the service using Http.post method. Here is my app ...

Utilizing the Angular *ngFor directive to iterate through JSON data

Just stepping into the world of Angular, I want to share a brief overview of my goal since the code is lengthy. Here's the relevant part: Within my project, I have a list display component. And I have two components, namely animals and zone. For in ...

What are some ways to access Angular's form array within HTML code?

.ts import { Component, OnInit } from '@angular/core'; import { HelloServiceService } from 'src/app/hello-service.service'; import { FormBuilder, FormGroup, FormControl, FormArray, Validators } from '@angular/forms'; @Compone ...

Base class protected properties are absent following the exclusion of another property

In my implementation, I have a generic base service that handles CRUD operations while the subclasses specify a specific entity and its endpoint URL. The base class sets a protected API URL property that each subclass initializes in the constructor. Recen ...

Simplify typing in TypeScript using default generic parameters

Imagine I came across the following object: const inquiries = { whoCreatesIssues: { options: { sameTeam: { id: 'SAME_TEAM' }, management: { id: 'MANAGEMENT' ...

Error encountered: `npm ERR! code E503`

While attempting to execute npm install on my project, which was cloned from my GitHub repository, I encountered the following error: npm ERR! code E503 npm ERR! 503 Maximum threads for service reached: fs-extra@https://registry.npmjs.org/fs-extra/-/fs-ex ...

The return type is not undefined but the switch covers all possibilities

I'm struggling to understand the issue with this simple example interface List { "A": false, "B": false, } // The function is missing a return statement and its return type does not include 'undefined'.ts(2366) / ...

Using ngIf for various types of keys within a JavaScript array

concerts: [ { key: "field_concerts_time", lbl: "Date" }, { key: ["field_concert_fromtime", "field_concert_totime"], lbl: "Time", concat: "to" }, { key: "field_concerts_agereq", lbl: "Age R ...

Issues arise when attempting to include the src attribute within the template tag in a Vuejs and Laravel project

After starting a project with Vuejs and Laravel using Laravel Mix, I encountered an issue. When attempting to split my component into separate files and load them in the .vue file as follows: <template src="./comp.html"></template> &l ...

What is the accurate type of control parameter in Typescript?

Recently, I developed a TypeScript React component called FormInput to use in my form. This component integrates the MUI framework and react-hook-form. However, I encountered an issue while trying to set the correct type for the "control" parameter in my c ...

Issue with Nestjs and Jest: expect().toHaveReturnedWith() not returning any value

Currently experimenting with nestjs and jest in a personal project, I've encountered some challenges while trying to properly utilize the expect().toHaveReturnedWith() methods. I wonder if the issue lies in how I set the resolved value: jest.spyOn(su ...

Having trouble with routerLink in your custom library while using Angular 4?

In my Angular 4 project, I have developed a custom sidebar library and integrated it into the main project. My current issue is that I want to provide the option for users to "open in new tab/window" from the browser's context menu without having the ...

The invocation of `prisma.profile.findUnique()` is invalid due to inconsistent column data. An invalid character 'u' was found at index 0, resulting in a malformed ObjectID

The project I'm working on is built using Next.js with Prisma and MongoDB integration. Below is the content of my Prisma schema file: generator client { provider = "prisma-client-js" } datasource db { provider = "mongodb" url = env("DATABA ...

What could be causing the Uncaught Error to persist even after using .catch()?

Check out this code snippet: function pause(ms:number) { return new Promise((resolve:any,reject:any) => setTimeout(resolve,ms)) } async function throwError(): Promise<void> { await pause(2000) console.log("error throw") throw new ...

Switching from module.exports in Javascript to Typescript format

My Node-express code currently uses module.exports to export functions. As I am converting the code to TypeScript, I need to find out how to replace module.exports in typescript. Can you help me with this? ...

Encountering error code TS1003 while trying to access object properties using bracket notation in Typescript

How can object property be referenced using bracket notation in TypeScript? In traditional JavaScript, it can be done like this: getValue(object, key) { return object[key]; } By calling getValue({someKey: 1}, "someKey"), the function will return 1. H ...

Could a variable (not an element) be defined and controlled within an Angular 2 template?

For instance, envision a scenario where I have a series of input fields and I wish to assign the 'tab' attribute to them sequentially as we move down the page. Rather than hard-coding the tab numbers, I prefer to utilize a method that automatical ...

Explore all user-defined properties of a specified type using the TypeScript Compiler API

Consider the following model structure: interface Address{ country: string; } interface Author{ authorId: number; authorName:string; address: Address; } interface Book{ bookId:string; title: string; author : Author; } I want to iterate th ...

eliminate any redundant use of generics

Recently, I attempted to create a pull request on GitHub by adding generics to a method call. This method passes the generically typed data to an interface that determines the return type of its methods. However, the linter started flagging an issue: ERR ...

Adding the unzip feature is not within my capabilities

I am a novice Japanese web developer. Unfortunately, my English skills are not great. I apologize for any inconvenience. I am interested in utilizing this specific module: https://www.npmjs.com/package/unzip To do so, I executed the following commands ...