镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Cannot extend mapped types #12986

Description

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.

Activity

  1. ahejlsberg commented on Dec 16, 2016

    @ahejlsberg
    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 };
  2. rotemdan commented on Dec 16, 2016

    @rotemdan

    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.

  3. kimamula commented on Dec 30, 2016

    @kimamula
    Contributor

    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>;
      }
    }

    Anders Hejlsberg (@ahejlsberg)'s workaround does not work in this situation.

  4. added
    FixedA PR has been merged for this issue
    and removed on Jan 21, 2017
  5. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions