้•œๅƒ็ซ™็‚น ยท ๆœฌ้กต็”ฑ็ฌฌไธ‰ๆ–น GitHub ๅช่ฏป้•œๅƒๆไพ›๏ผŒ้ž GitHub ๅฎ˜ๆ–น็ซ™็‚น๏ผŒไธๆŽฅๅ—ไปปไฝ•็™ปๅฝ•ๆˆ–ๅ‡ญๆฎ่พ“ๅ…ฅใ€‚ๅ‰ๅพ€ github.com
Skip to content

Union tuple type in rest argument can't accpect less argument.ย #48663

Description

@takanara1994

Bug Report

๐Ÿ”Ž Search Terms

source has but target allows only

๐Ÿ•— Version & Regression Information

  • This is a crash

โฏ Playground Link

Playground link with relevant code

๐Ÿ’ป Code

const func: (...args: [number, string] | [string, number]) => void = (item) => { }

๐Ÿ™ Actual behavior

throw error

Type '(item: string | number) => void' is not assignable to type '(...args: [number, string] | [string, number]) => void'.
  Types of parameters 'item' and 'args' are incompatible.
    Type '[number, string] | [string, number]' is not assignable to type '[item: string | number]'.
      Type '[number, string]' is not assignable to type '[item: string | number]'.
        Source has 2 element(s) but target allows only 1.

๐Ÿ™‚ Expected behavior

no error

Activity

  1. MartinJohns commented on Apr 13, 2022

    @MartinJohns
    Contributor

    Duplicate of #45972. Used search terms: `source has but target allows only"

  2. jcalz commented on Apr 13, 2022

    @jcalz
    Contributor

    I'm... not sure this is a duplicate of that, since there are no leading rest elements here to make the analysis weirder. Maybe the same underlying issue is happening in both places?

    Anyway this one feels more like a bug to me, since the following is fine:

    const f1: (x: string | number) => void = x => { }; 
    const f2: (x: string | number, y: string | number) => void = f1; // okay
    const f3: (...args: [number, string] | [string, number]) => void = f2; // okay

    And while transitivity of assignability isn't the be-all and end-all for TypeScript, it's nice to be able to reason about things this way when possible.

  3. graphemecluster commented on May 29, 2022

    @graphemecluster
    Contributor

    Sorry to copy my #49218 (comment) here:

    I think the easiest way to solve all the related issues is to wrap all the arguments into a tuple with rest syntax, i.e. item => {} should become (...[item]) => {} and ([first, ...rest], foo, ...args) => {} should work just like (...[[first, ...rest], foo, ...args]) => {}.

  4. cdauth commented on Jun 25, 2024

    @cdauth

    Not exactly the same issue, but probably the same root cause:

    const func: (arg1: string, arg2?: string) => void = (...args: [string] | [string, string]) => undefined; // Error

    Also:

    type Func = (...args: [string] | [string, string]) => void;
    type Test = Func extends (arg1: string, ...args: any[]) => any ? true : false; // false
    
    // Workaround:
    type Test = Func extends (...args: infer Args) => any ? (Args extends [string, ...any[]] ? true : false) : false; // true
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

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions