Skip to content

Function signature overload with rest parameter : TS picks the wrong signature when called with argument any[]Β #62000

Closed as not planned
@denis-migdal

Description

@denis-migdal

πŸ”Ž Search Terms

function signature wrong pick

πŸ•— Version & Regression Information

  • Tested with the nightly build.

⏯ Playground Link

Playground Link

πŸ’» Code

type Extension = {
    args: Record<string, any>
};

// black magic from https://www.geeksforgeeks.org/union-type-to-intersection-type-in-typescript/
type UnionToIntersection<U> = (
    U extends any ? (k: U) => void : never
) extends (k: infer I) => void
    ? I
    : never;

type Args<T extends Extension[]> = UnionToIntersection<T[keyof T & number]["args"]>

export function LISS(args: NoInfer<Args<[{args: {css: string[]}}]>>)
                                        : true
export function LISS<T extends Extension[]>( args: NoInfer<Args<T>>,
                                        ...extensions: T): false
export function LISS<T extends Extension[]>(args: NoInfer<Args<T>>,
                                    ...extensions: T): boolean {
                                        return {} as boolean
                                    }

const a = LISS({ css: [] as any[]}); // should be true
const b = LISS({ css: [] as string[]}); // ok

πŸ™ Actual behavior

typeof a is false when it should be true : i.e. the second signature overload is chosen.

πŸ™‚ Expected behavior

typeof a should be true : i.e. the first signature overload should be chosen.

Additional information about the issue

Using T extends [Extension, ...Extension[]] fixes the issue in the example (force the second signature to have at least one extension). But the underlying issue might manifest in other cases.

Note: It would be simpler to write :

const exts = [{args: {css: string[]}}];

export function LISS<T extends Extension[] = typeof exts>(
                                        args: NoInfer<Args<T>>,
                                        ...extensions: T = exts): ...`

But TS doesn't allow us to do so, hence the function signature overload.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Not a DefectThis behavior is one of several equally-correct options

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions