[Typescript] Function overload :The "Instantiated with Subtype" Error

import { Equal, Expect } from "../helpers/type-utils";

const obj = {
  a: 1,
  b: 2,
  c: 3,
} as const;

type ObjKey = keyof typeof obj;

//Type '"a"' is not assignable to type 'TKey'.
//  '"a"' is assignable to the constraint of type 'TKey', but 'TKey' could be instantiated with a different subtype of constraint '"a" | "b" | "c"'.
const getObjValue = <TKey extends ObjKey>(key: TKey = "a") => {
  return obj[key];
};

const one = getObjValue("a");
const oneByDefault = getObjValue();
const two = getObjValue("b");
const three = getObjValue("c");

type tests = [
  Expect<Equal<typeof one, 1>>,
  Expect<Equal<typeof oneByDefault, 1>>, // doesn't work
  Expect<Equal<typeof two, 2>>,
  Expect<Equal<typeof three, 3>>
];

 

Solution:

1. One overload with no param

2. One overload with param

3. Implemtation should be loosen type and compatiable with both overloads

 

const obj = {
  a: 1,
  b: 2,
  c: 3,
} as const;

type ObjKey = keyof typeof obj;

// function with no param
function getObjValue(): typeof obj['a'];
// function with one param
function getObjValue<TKey extends ObjKey>(key: TKey): typeof obj[TKey];
// implementation doesn't need generic, because it can infer from function overload
// to be compatiable with both overload
// we need to add default value 'a'
function getObjValue(key: ObjKey = 'a') {
  return obj[key];
}

 

You can also add return type for implemtation:

function getObjValue(): typeof obj['a'];
function getObjValue<TKey extends ObjKey>(key: TKey): typeof obj[TKey];
function getObjValue(key: ObjKey = 'a'): 1 | typeof obj[ObjKey] {
  return obj[key];
}

 

posted @ 2023-02-08 15:57  Zhentiw  阅读(24)  评论(0编辑  收藏  举报