首页 文章

自TypeScript 2.7以来缺乏类型签名

提问于
浏览
1

这篇文章适用于TypeScript 2.6:

function resolver<Key extends keyof HashType>(a: Command<Key>): HashType[Key]['out'] {
  return handlers[a.kind](a);
}


const handlers: {[k in keyof HashType]: (arg: Command<k>) => HashType[k]['out']} = {
  a: arg => 1,
  b: arg => ''
};

type Command<Key extends keyof HashType> = HashType[Key]['in'] & { kind: Key }


type HashType = {
  a: { in: { someString: string }, out: number }
  b: { in: { someNumber: number }, out: string }
}

但是,自 2.7 以来,它失败了:

TS2349:无法调用类型缺少调用签名的表达式 . 输入'((arg:Command <“a”>)=>数字)| ((arg:Command <“b”>)=> string)'没有兼容的呼叫签名 .

Here's the same thing in a playground.

1 回答

  • 1

    我没有足够聪明地意识到 handlers[a.kind] 的类型与 a 相关 .

    请考虑以下有效但令人讨厌的代码:

    const resolved = resolver<"a" | "b">({ someString: "whoops", kind: "b" });
    

    Key extends keyof HashType 开始, Key 可以等于 keyof HashType . 请注意,给出的参数是 Command<keyof HashType> ,即使它既不是 Command<"a"> 也不是 Command<"b"> . 编译器无法保证 handlers[a.kind] 适用于 a .

    这可能是现实生活中使用代码的问题吗?可能不是 . 如果没有,您可以声称您比编译器更了解并使用type assertion

    function resolver<Key extends keyof HashType>(a: Command<Key>): HashType[Key]['out'] {
      const handler = handlers[a.kind] as (arg: Command<Key>) => HashType[Key]['out'];
      return handler(a);
    }
    

    现在代码编译愉快 . 如果你担心有人会在代码中传递过多的参数,那么就有办法解决它 . 但它可能不值得 .

    希望有所帮助!有关类似问题,请参阅this question .

相关问题