Skip to content

Unable to declare an interface that extends Record<string, nonAnyType> with additional support functions. #58256

Closed as not planned

Description

🔎 Search Terms

interface method index accessor
method index type 'string'

🕗 Version & Regression Information

The bug occurs at the latest stable version published on npm. ts-loader 9.5.1 is also used in the project where this problem occurs.
The earlier versions have not been tested, but they are very likely to have the same behavior.

⏯ Playground Link

No response

💻 Code

export interface RawHeaders extends Record<Exclude <string, "get">, string[]> {
	get(key: string): string[];
}

🙁 Actual behavior

The Record<Exclude<string, "somestring">, string[]> type is being treated as a Record<string, string> type, which causes following error message at the line where I declared the get method:

Property 'get' of type '(key: string) => string[]' is not assignable to 'string' index type 'string[]'.

It also shows the same error message at the same line when using an index accessor without extending Record:

export interface RawHeaders {
	[k: Exclude<string, "get">]: string;
	get(key: string): string[];
}

🙂 Expected behavior

It should not show any errors since the key get is excluded when extending the Record interface.

Additional information about the issue

I have not found any valid solutions that would allow a Record<string, nonAnyType> interface to declare additional methods without making the value of the index accessor any, which I believe most developers would not like since it makes the code unchecked, and so is hard to place documentations. This could also confuse new developers when making a library, since it loses the advantages of using TypeScript over plain JS.

Edit:

The solution of using an intersection type works, but I don't think this design to very logical, as in reality not all keys are allocated by a Record like this. Furthermore built-in Object functions accessible, and can coexist with the interface:

interface K {
	[k: string]: string;
}
let d : K = Object.create(null);
d.toString();

whereas custom method declarations can only be a type, which makes it un-extendable by another interface, and un-implementable by a class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions