Skip to content

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

Open
@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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions