Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot extend mapped types #12986

Closed
fongandrew opened this issue Dec 16, 2016 · 3 comments
Closed

Cannot extend mapped types #12986

fongandrew opened this issue Dec 16, 2016 · 3 comments
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript

Comments

@fongandrew
Copy link

TypeScript Version: 2.1.4

Code

interface A {
    x: number;
}

interface B extends Partial<A> {
    y: number;
}

Expected behavior: Compiles

Actual behavior: An interface may only extend a class or another interface.

@mhegazy mhegazy added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Dec 16, 2016
@ahejlsberg
Copy link
Member

This is not an easy change as it would require some deeper architectural reworking. Note that you can accomplish pretty much the same effect with the intersection type operator:

type B = Partial<A> & { y: number };

@rotemdan
Copy link

rotemdan commented Dec 16, 2016

Just wanted to add: I have considered suggesting this myself, though one thing I must mention is that even if it was made possible to inherit from computed types, that would still miss a significant use case for them as generators of "templates" for new types (rather than serving as base types). I'll try to demonstrate:

Let's say I have an existing type of this shape:

type SomeType = {
	a: number;
	b: boolean;
	c: string;
}

Now I want to declare a type that has the same exact keys only each key is now mapped to a an object that has a property val with the type of the corresponding key in SomeType. Mapped types allow me to do that:

type MyMappedType<T> = { [ P in keyof T]: { val: T[P] } };
type Result = MyMappedType<SomeType>;

Now I want to customize the resulting type, so the closest thing the language provides me is to "inherit" from that mapped type. Let's assume that was possible:

interface MyInterface extends MyMappedType<SomeType> {
	a: { val: number, x: string[], y: boolean[] };
	b: { val: boolean, z: number };
}

There's only one problem here:

I forgot to specify property c, so it "fell back" to { val: string }, however the compiler didn't tell me anything went wrong! why? because I used the wrong operator.

What if what I want is not to "inherit" from the mapped type, but simply use it as a "model" or "constraint" for the new type?

I have tried my best to propose a solution in #12942. It's still in an early stage though. I've submitted it at least with the hope that it might influence or inspire the typescript team to include something of that sort in the future, even if it eventually appears with a different syntax or in a more limited form.

@kimamula
Copy link
Contributor

kimamula commented Dec 30, 2016

I am trying to develop Vue.js app with TypeScript and also having a trouble because of the limitation that mapped types are not available in classes or interfaces.

In Vue.js, you can pass props to a component (just like React) and the properties of props are injected into the properties of the component instance.
Therefore, the declaration of the class of Vue component should be something like this, which is not possible currently.

declare class Vue<Props> {
  [P in keyof Props]: Props[P];
}

// example usage
class Foo extends Vue<{ message: string }> {
  render(h) {
    return <span>{this.message}</span>;
  }
}

@ahejlsberg's workaround does not work in this situation.

@mhegazy mhegazy added Fixed A PR has been merged for this issue and removed In Discussion Not yet reached consensus labels Jan 21, 2017
@mhegazy mhegazy added this to the TypeScript 2.2 milestone Jan 21, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

5 participants