#Typescript is inferring to string instead of specific string literal

5 messages · Page 1 of 1 (latest)

gilded cedar
#

I have a generic function lets call it func. Each argument in the function is of type string | [string, Function] . For simplicity the func is returning the argument array as it is.

function func <T extends (string | [string, Function])[]>(...args: T): T {
  return args
}

const re = func('a', ['b', () => {}])

I call func('a', ['b', () => {}], 'c') the return type I get is ['a', [string, () => void], 'c'] What I want is ['a', ['b', () => void], 'c']. For the 1st and 3rd argument, the type is string literal but the second argument which is tuple, it fails to infer the string literal b and instead it is string.

// not working
function func <T extends (string | readonly [string, Function])[]>(...args: T): T {
  return args
}

// not working
function func <T extends readonly (string | [string, Function])[]>(...args: T): T {
  return args
}

It works, if I use const with second argument, but then it defeats the purpose.

// working but
const re = func('a', ['b', () => {}] as const)

So, is there any way, this can be achieved without specifying the argument as const . I have tried using readonly in the function type definition, but still the same inference.

main urchin
#

Use const generic.

storm impBOT
#
function func<const T extends (string | [string, Function])[]>(...args: T): T {
    return args
}

const re = func('a', ['b', () => {}])
//    ^? - const re: ["a", ["b", () => void]]
main urchin
#

On a side note, Function is not a good type to use, so you might want to use something else if the code isn't just a made up example.

gilded cedar