typescript - 验证一个参数(它是一个函数)可以用同级参数调用
问题描述
我正在编写一些高阶函数,并且发现很难编写类型来验证作为参数提供的函数可以与提供的其他参数一起调用。这是一个超级基本的例子:
function(myFunc, arg1, arg2) {
return myFunc(arg1, arg2) // We want to verify that this is typesafe at compile time
}
还有一个更现实的例子:
// Here's a higher order function that returns a function that alters input in some way
type algorithm = (input: number, options?: any) => number;
const createHandler = (algorithm: algorithm, options?) =>
(input: number) => algorithm(input, options);
// This algorithm needs no 'options' configuration
const addOne = (input) => input + 1;
// This algorithm requires a specific 'options' configuration
interface PowerOptions { value: number; }
const power = (input: number, {value}: PowerOptions) => input ** value
// Now when I create these handlers, I'd like for the 'options' to be validated against the provided function
const addOneHandler = createHandler(addOne);
const squaredHandler = createHandler(power, { value: 2 });
const cubedHandler = createHandler(power, {}); // This should show a type error as the options are invalid for the algorithm
解决方案
关于您的基本示例,您可以通过类型推断来检查所提供函数的类型安全性(在 Typescript Playground 上检查):
const a = function <U, V>(myFunc: (arg1: U, arg2: V) => any, arg1: U, arg2: V) {
return myFunc(arg1, arg2)
}
const doubleIfTrue = (arg1: number, arg2: boolean) => arg2 ? 2 * arg1 : arg1
console.log(a(doubleIfTrue, 1, true)) // Type OK
console.log(a(doubleIfTrue, 1, "hop")) // Wrong type: number and string provided
在这种情况下,U
根据V
提供的函数的参数推断类型。
但是您想要实现的目标会变得更加复杂。根据您的代码,我可以整理出一些东西(在 Typescript Playground 上查看):
type algorithm<OPT = null> = (input: number, options?: OPT) => number;
type algorithmOptions<A> = A extends algorithm<infer OPT> ? OPT : null
const createHandler = <A extends algorithm<any>>(algorithm: A, options: algorithmOptions<A>) =>
(input: number) => algorithm(input, options);
// Algorithms
const addOne:algorithm = (input: number) => input + 1;
interface PowerOptions { value: number; }
const power:algorithm<PowerOptions> = (input: number, {value}) => input ** value
// Handlers
const squaredHandler = createHandler(power, { value: 2 }); // correct
const addOneHandler = createHandler(addOne, null); // correct if a second argument is provided
const addOneHandlerFailing = createHandler(addOne, { value: 2 }); // wrong because an argument is provided
const squaredHandlerFailing1 = createHandler(power, {}); // wrong because of argument interface not respected
const squaredHandlerFailing2 = createHandler(power); // wrong because no argument provided
使用一些条件类型来检索算法参数。但也许我走得太远了,你可以找到一种更简单的方法
另一件事:据我所知,在某些情况下,options 参数似乎createHandler
不能是可选的,而在另一些情况下是强制性的,而不会将示例变得更复杂。
我希望它有帮助!
推荐阅读
- kentico - 您可以在同一个网站中结合 Kentico 12 MVC 和 Kentico 12 Portal Engine 开发吗?
- c++ - 初始化后,Visual Studio C++ 指针不为 NULL
- excel - 我们如何使用 Pandas 和 Robot Framework
- python - 如何覆盖 QDialog.accept()?
- python - 分类问题的准确度得分低
- azure - 有没有办法在 Azure 的应用程序网关中确认 SSL/TSL 终止是否正常工作
- ios - 带有右栏按钮问题的大型导航栏
- javascript - 默认情况下启用自动修复。使用单字符串形式
- android - OnePlus Expresso 测试运行问题 (Android Studio 3.6.2)
- emacs - 启动 Emacs 时如何防止打开特定的缓冲区