Guichi
Guichi

Reputation: 2341

How come the indexed type is `never`

type X = { aa: number; bb: string };
const get = <Key extends keyof X>(key: Key) => {
  type T<Value extends X[Key]> = Value;
  const a: T<any>;
  /**
   * Type 'string' does not satisfy the constraint 'X[Key]'.
    Type 'string' is not assignable to type 'never'.
   */
  const b: T<string>; 
};

From my opinion, Value should be of type string|number, how it was calculated as never by typescript

Upvotes: 0

Views: 160

Answers (1)

mahooresorkh
mahooresorkh

Reputation: 1444

You wrote the ‍get‍ function in such a way that when it calls, it can be given any type as a generic parameter, that is the subset of X keys. So the condition in T<Value extends X[Key]> is ambiguous for typescript. For example :

get<"aa">("aa") results T<Value extends number>

get<"bb">("bb") results T<Value extends string>

get<"aa" | "bb">("bb") results T<Value extends string | number>

Thus when you do const b: T<string>;, it does not know what the condition exactly is and it says:

Type 'string' does not satisfy the constraint 'X[Key]'

I don't know the purpose of the function in your project, but I think it can be rewritten in this way using conditional types:

type X = { aa: number; bb: string };
const get = () => {
  type MyType<Value, K extends keyof X = keyof X> = Value extends X[K] ? Value : never; 
    const a: MyType<any> = true;  //------> any other value can be assigned
    const b: MyType<string> = "Test"; // -------> it is string type 
};

I hope it helps you.

By the way you can read more about conditional types here.

Upvotes: 1

Related Questions