【问题标题】:Typescript invoke function from object index with generic typeTypescript 从具有泛型类型的对象索引调用函数
【发布时间】:2019-08-23 01:30:11
【问题描述】:

我正在尝试在 Typescript 中使用泛型,将泛型参数用作索引来调用存储在对象中的函数。
我收到的错误是:

[ts] 无法调用类型缺少调用签名的表达式。输入 '((变量: { insertId: number; }) => string) | ((变量:{ updateId:数字;值:字符串;})=>字符串)| ((variable: { deleteId: number; }) => string)' 没有兼容的调用签名。 [2349]

'QueryInput[T]' 类型的参数不能分配给'{ insertId: number; 类型的参数。 } & { updateId: number;值:字符串; } & { deleteId: number; }'。 键入'{ insertId:数字; } | { updateId:数字;值:字符串; } | { deleteId:数字; }' 不可分配给类型 '{ insertId: number; } & { updateId: number;值:字符串; } & { deleteId: number; }'。 键入'{ insertId:数字; }' 不可分配给类型 '{ insertId: number; } & { updateId: number;值:字符串; } & { deleteId: number; }'。 键入'{ insertId:数字; }' 缺少来自类型 '{ updateId: number; 的以下属性值:字符串; }':updateId,值 类型 'QueryInput[T]' 不可分配给类型 '{ insertId: number; }'。 键入'{ insertId:数字; } | { updateId:数字;值:字符串; } | { deleteId:数字; }' 不可分配给类型 '{ insertId: number; }'。 '{ updateId: number; 类型中缺少属性 'insertId'值:字符串; }' 但在 '{ insertId: number; 类型中是必需的}'.ts(2345) App.tsx(7, 13): 'insertId' 在这里声明。 (参数)变量:QueryInput[T]

这是一个复制问题的示例代码:

type Query = "insert" | "update" | "delete";

interface QueryInput {
  insert: { insertId: number };
  update: { updateId: number; value: string };
  delete: { deleteId: number };
}

type QueryObject = { [T in Query]: (variable: QueryInput[T]) => string };

const queries: QueryObject = {
  insert: variable => "insert",
  update: ({ updateId, value }) => "update",
  delete: variable => "delete"
};

const getQuery = <T extends Query>(query: T, variables: QueryInput[T]) => {
  return queries[query](variables); // this line throws an error
}

Typescript 引擎似乎无法解析函数的正确签名 - 尽管肯定只有 1 个可能的签名(从 queries[query] 返回的那个)。
看来queryvariables 已正确解析,并且具有适当的类型。

【问题讨论】:

  • 它无法推断variables 的类型,因为query 的值只有在运行时才知道。因此 TypeScript 无法推断出 queries[query] 是什么,因此它假定它是所有可能的类型,但随后您声明 variables 只能是其中一种类型,它不知道是哪一种。
  • 就像我写的那样,查询和变量正确解析了。

标签: typescript generics web


【解决方案1】:

如果您想要一个快速的肮脏解决方案来使其编译,

const getQuery = <T extends Query>(query: T, variables: QueryInput[T]) => {
  let v: any = variables;
  return queries[query](v); // this line doesnt throw an error
}

这并不理想,但 getQuery 本身似乎不需要改变。 并且 getQuery 的使用仍将根据您的需要在此解决方案中输入,只是它的实现不会。

直到你找到更好的解决方案..

【讨论】:

  • 它也不起作用。它会在运行时引发相同的错误。
  • 谢谢!我不得不升级打字稿(我有 3.2.4、3.4.1 的工作),你的解决方案成功了。
猜你喜欢
  • 1970-01-01
  • 2021-02-22
  • 2017-08-04
  • 2020-01-02
  • 2020-05-13
  • 2021-12-30
  • 2023-03-09
  • 2020-11-15
  • 2020-12-24
相关资源
最近更新 更多