Skip to content

Interface 'MyInterface<T>' incorrectly extends interface - for named tuple type that has '...rest' param #51751

Open

Description

@pmunin

Bug Report

Error happens only when:

  • MyInterface extends type alias which represents named array tuple
  • MyInterface is generic
  • MyType is NAMED tuple
  • MyType has ...rest

🔎 Search Terms

type alias, named tuple, interface

🕗 Version & Regression Information

Typescript v4.9.3

⏯ Playground Link

Playground link with relevant code

💻 Code

The following code throws that error:

type MyType = [
  name1:string,
  name2: number,
  ...rest:any[]
]

interface MyInterface<T> extends MyType {
}

// "Interface 'MyInterface<T>' incorrectly extends interface '[name1: string, name2: number, ...rest: any[]]'.

All of the following below works fine:

type MyType = [
  name1:string,
  name2: number,
  ...rest:any[]
]

interface MyInterface extends MyType { //MyInterface is not generic => works
}

// ----------- OR -------------

type MyType = [ // MyType does not have ...rest => works fine
  name1:string,
  name2: number
]

interface MyInterface<T> extends MyType {
}

// ------------ OR ------------
type MyType = [ // MyType typle elements are not named => works fine
  string,
  number,
  ...any[]
]

interface MyInterface<T> extends MyType {
}

🙁 Actual behavior

TSC throws error:

Interface 'MyInterface<T>' incorrectly extends interface '[name1: string, name2: number, ...rest: any[]]'.

🙂 Expected behavior

Successfull compilation

Activity

  1. RyanCavanaugh commented on Dec 5, 2022

    @RyanCavanaugh
    Member

    This is probably going to be extremely difficult to fix (or possibly trivial?). Weird stuff.

  2. fatcerberus commented on Dec 6, 2022

    @fatcerberus

    fwiw having an interface extend a tuple seems like an odd thing to do in the first place. If the interface has any properties or methods then I don’t think you can even construct a legal value (without type assertions, anyway).

  3. pmunin commented on Dec 7, 2022

    @pmunin
    Author

    fwiw having an interface extend a tuple seems like an odd thing to do

    The main (maybe only?) reason to use interface vs type alias is ability to merge declarations. That constraint of type alias was an odd design decision, also even having types+interfaces vs just one of those that combines everything is weird and confusing

  4. Andarist commented on Mar 24, 2023

    @Andarist
    Contributor

    It probably wouldn't be that hard to fix but it would increase the complexity of the code a little bit.

    It doesn't work because the interface checks if it's extending the base type correctly. To do that it checks if that resulting interface it's assignable to all of its bases. So it's checking if MyInterface<T> to [string, number, ...any[]]. The target is a tuple type but the source is not an array and it's not a tuple and since the target tuple is variable the propertiesRelatedTo determines that this source is not assignable to this target.

    The case with MyInterface works OK because this type manages to get normalized during prior stages and it becomes equivalent to its base. Note that adding any properties to MyInterface prevents that and it also errors.

    Cases without a variable element on that tuple likely work because the compiler is able to get past that "is tuple variable" check and actually gets to comparing object properties~.

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

    BugA bug in TypeScriptDomain: Something ElseFallback label when we just can't figure anything else outHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions