- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
是否可以推断
重载函数的参数?
例如:
type MyFunction = {
(key: "one", params: { first: string }): void;
(key: "two", params: { second: string }): void;
}
type MyFunctionParams<T extends string> = MyFunction extends (
key: T,
params: infer P,
) => void
? P
: never;
// should be `{ first: string }`
type OneParams = MyFunctionParams<"one"> // never
最佳答案
如果您控制MyFunction
的定义,我会遵循caTS's excellent approach从另一个角度来看它。 (有时令人惊讶的是,如果您改变起点,就可以简化某些事情,甚至可以使原本不可能的事情成为可能,而且通常不会产生负面后果。)
但是,如果您必须使用现有的 MyFunction
类型,那么: 两种可能的解决方案,一种是通用的,另一种是更实用的有针对性的,坦率地说,这两种解决方案都不如我们可能希望的那样令人满意喜欢:
遗憾的是,访问函数重载类型的参数信息(或返回类型信息)非常困难和冗长——但有可能。如 this question's answers 中所述,这只是 Parameters
和 ReturnType
的限制,它们无法按照我们想要的方式处理重载。你的问题就是一个很好的例子。这是一个更简单的 ( playground ):
type MyFunction = {
(key: "one", params: { first: string }): void;
(key: "two", params: { second: string }): void;
};
type MyFunctionKey = Parameters<MyFunction>[0];
// ^? type MyFunctionKey = "two"
// Huh?!? I think most of us would expect `"one" | "two"`, but
// that's just not the way it is. (There's usually a good reason
// for these limitations in the general case, but...)
但它是可能的在合理范围内,在这种情况下,“合理”是函数可能重载的合理最大数量。让我们将 6 作为我们的最大过载限制。
从Titian's answer to that question可以看出,可以知道一个函数有多少重载,并推断出它们的参数列表。例如:
type Whatever<F> =
F extends {
(...args: infer Params1): any);
(...args: infer Params2): any);
}
? // This branch is used if F has **exactly** two overloads
: // Otherwise this one is
;
我们可以使用该机制来处理 2、3、4、5...直到您想要可能的重载集的任何合理限制。所以这是我们难题的第一部分,MyFunctonParams
根据参数帮助器类型有多少重载进行分派(dispatch):
type MyFunctionParams<KeyType> =
MyFunction extends {
(...args: infer P1): any;
(...args: infer P2): any;
}
? ParamsHelper<KeyType, P1, P2>
: MyFunction extends {
(...args: infer P1): any;
(...args: infer P2): any;
(...args: infer P3): any;
}
? ParamsHelper<KeyType, P1, P2, P3>
: MyFunction extends {
(...args: infer P1): any;
(...args: infer P2): any;
(...args: infer P3): any;
(...args: infer P4): any;
}
? ParamsHelper<KeyType, P1, P2, P3, P4>
: MyFunction extends {
(...args: infer P1): any;
(...args: infer P2): any;
(...args: infer P3): any;
(...args: infer P4): any;
(...args: infer P5): any;
}
? ParamsHelper<KeyType, P1, P2, P3, P4, P5>
: MyFunction extends {
(...args: infer P1): any;
(...args: infer P2): any;
(...args: infer P3): any;
(...args: infer P4): any;
(...args: infer P5): any;
(...args: infer P6): any;
}
? ParamsHelper<KeyType, P1, P2, P3, P4, P5, P6>
: never;
ParamsHelper
的工作是将我们提供的 KeyType
与我们传递给它的每个参数元组的第一个元素(您的 key
)相匹配并提供第二个元素的类型(您的 params
):
type ParamsHelper<
KeyType,
P1 extends any[],
P2 extends any[] = [never, never],
P3 extends any[] = [never, never],
P4 extends any[] = [never, never],
P5 extends any[] = [never, never],
P6 extends any[] = [never, never]
> = KeyType extends P1[0]
? P1[1]
: KeyType extends P2[0]
? P2[1]
: KeyType extends P3[0]
? P3[1]
: KeyType extends P4[0]
? P4[1]
: KeyType extends P5[0]
? P5[1]
: KeyType extends P6[0]
? P6[1]
: never;
就是这样!现在我们得到了想要的结果,前提是 MyFunction
没有超过六个重载(或您决定设置的任何限制):
type OneParams = MyFunctionParams<"one">;
// ^? type OneParams = { first: string; }
type TwoParams = MyFunctionParams<"two">;
// ^? type TwoParams = { second: string; }
在该示例中,MyFunctionParams
绑定(bind)到 MyFunction
,但如果我们希望将函数类型传递到其中,我们可以制作一个通用版本。对于你的例子来说似乎有点矫枉过正,但是 here that is .
如果我们只是想处理MyFunction
,我们可能会采取更简洁和更有针对性的方法,像这样:
type MyFunction1 = {
(key: "one", params: { first: string }): void;
};
type MyFunction2 = {
(key: "two", params: { second: string }): void;
};
type MyFunction = MyFunction1 & MyFunction2;
type MyFunctionParams<KeyType> =
KeyType extends Parameters<MyFunction1>[0]
? Parameters<MyFunction1>[1]
: KeyType extends Parameters<MyFunction2>[0]
? Parameters<MyFunction2>[1]
: never;
type OneParams = MyFunctionParams<"one">;
// ^? type OneParams = { first: string; }
type TwoParams = MyFunctionParams<"two">;
// ^? type TwoParams = { second: string; }
不太令人满意,当然每次你添加另一个重载时,你都必须编辑 MyFunctionParams
类型来处理它,但有时更简单和有针对性的更好,这取决于你的情况.
关于typescript - 推断重载函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74208041/
当使用模板模板参数时,我如何推断或删除模板模板的模板类型? 考虑以下 SSCCE: #include #include #include using namespace std; templat
假设我有一些特质: trait A[T] { def foo: T } 一个扩展它的类: class B[T](t: T) extends A[T] { def foo = t } 以及父特征的子特征
一边玩-rectypes在某些时候选择 OCaml 我只是迷路了。 这个表达式几乎可以打字: # fun x -> x x;; - : ('a -> 'b as 'a) -> 'b = 但是这里 O
我正在编写一个类似 CRUD 的应用程序,并且通过主键进行大量查找(主键可以有不同的类型)。所以我定义了以下类型类: {-# LANGUAGE MultiParamTypeClasses #-} cl
我已经创建了关系 A 'is functional parent of' B并定义 'has functional parent'作为 'is functional parent of' 的倒数. '
给定一个使用 Kotlin 版本 1.3.61 和 JOOQ 版本 3.13.1 的系统,这样的方法会构建 union正常查询: val selectCommonPart = coalesce
考虑以下错误代码: fun x = if (null x) then 0 else (take 50 x) : (fun (drop 50 x)) 我注意到,我可以毫无问题地将它加载到
给定一个具有以下类型的函数 a: a::x -> Bool 和以下类型的另一个函数 b: b::Bool -> y 我正在尝试找出推断以下函数类型的步骤: c =\d -> d a b 有人可以帮助解
我正在尝试使用 Infer 工具来分析我的应用代码。我关注了these steps每次我尝试运行 infer -- gradle build 时,我都会收到以下错误: infer -- gradle
所以我制作了这个模板来定义内联仿函数: template struct AsFunctor { template std::invoke_result_t operator()(A
是否可以推断 CRTP 基类中模板化成员函数的返回类型? 虽然推断参数类型效果很好,但它因返回类型而失败。考虑以下示例。 #include template struct base { tem
使用 Series.interpolate 很容易在 Pandas.DataFrame 中插入值,如何进行外推? 例如,给定一个如图所示的 DataFrame,我们如何将它外推 14 个月到 2014
我想知道为什么这不起作用(缺少参数类型)? Seq(1,2,3).toSet.map(_ + 1) 但这确实: val foo = Seq(1,2,3).toSet foo.map(_ + 1)
我没有必要使用 SQLite3 shell 工具来维护一个小型数据库。我正在使用 -header -ascii标志,尽管据我所知,这适用于任何输出选择。我正在寻找一种方法来避免对返回的任何一个值的类型
我有以下组件 type PropTypes = { items: T[], header: (item: T) => React.Element, body: (item: T) => R
我想在 Eclipse/JSDT 中指定实例变量的类型,如下例所示: /** * @constructor */ function A() { /** @type Node */
我正在用 Python 编写一个方法,它看起来像这样: def rgb_to_grayscale(image): print(image.shape) pass 此处预期的类型是 nu
我有一个 my_values 数组,我正在尝试为其推断 true_values 数组中最接近、较小的值。使用下面的 find_nearest 函数并不能完成我想要的。我如何追加它以找到最近的、较小的值
在下面的代码中: template int b(int q, const std::array& types) { int r = q; for (int t : types)
在 Pandas DataFrame 中插入 NaN 单元非常容易: In [98]: df Out[98]: neg neu pos av
我是一名优秀的程序员,十分优秀!