0

I have this code

type Check<F, T> = F extends string
  ? string
  : T

type Func2 = <F extends T[] | string, T>(functor: F) => Check<F, T>

const x: Func2 = (x: any) => x[0]

const y = x([1, 2])
const z = x("abc")

I am getting type unknown for y while it is perfectly fine for z.

The type inferred for calling x for y is -

const x: <number[], unknown>(functor: number[]) => unknown

Why there is unknown for T but T[] is inferred properly?

Playground

2
  • There's no inference site for T in the signature of x. F can be inferred by the type of functor, but nothing you're passing in will fix T so it falls back to unknown. And so F is only constrained to unknown[] | string. I'm not sure why you'd prefer your definition of Func2 over something like type Func2 = <F extends { [k: number]: any }>(functor: F) => F[0]. Can you explain what you're trying to do and why you're trying to do it this way? Commented Sep 26, 2020 at 19:19
  • @jcalz The actual code contains other types as well. Check this for the actual code. Commented Sep 26, 2020 at 20:14

1 Answer 1

2

Why does this happen?

Type inference in TS doesn't work as you expect. Type variables could be inferred as I think in three ways:

  • based on an argument of a function that has been passed;
  • based on analysis of return value of a function;
  • based on previously inferred type variables (this rule applied only from left to right order);

That's why you have got unknown type.


Solution in your case could be:

type Check<F, T> = F extends (infer U)[]
  ? U
  : T

type Func2 = <F extends any[] | string>(functor: F) => Check<F, string>

const x: Func2 = (x: any) => x[0]

const y = x([1, 2])
const z = x("abc")
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you @Николай Гольцев The solution did work for me. But the inferred signature is correct const x: <number[], unknown>(functor: number[]) => unknown. Please check the playground
Yes, it's my mistake, you're right! Answer updated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.