如何使用类型参数调用 const 函数?
How to call const function with type arguments?
根据 redux-form
typings 的定义:
export type DataSelector<FormData = {}, State = {}> = (formName: string, getFormState?: GetFormState) => (state: State) => FormData;
export const getFormValues: DataSelector;
请注意 DataSelector
有两个类型参数。如果我调用 getFormValues
,这是一个 const
函数,我该如何提供类型参数?
type FormFields = { name: string };
// No type argument specified so: Property 'name' does not exist on type '{}'.
const name = getFormValues('my-form')(state)?.name;
// I could cast it, but no thank you ...
const name = (getFormValues('my-form')(state) as any as FormFields)?.name;
// Need to supply `FormFields` as the generic argument for `FormData`, but how? This doesn't work ...
const name = getFormValues<FormFields>('my-form')(state)?.name;
- 我能否以某种方式为
const
函数指定通用参数?
- 打字有误吗?如何纠正它们?
更新: 这种情况下的输入不正确。而不是...
export type DataSelector<FormData = {}, State = {}> = (formName: string, getFormState?: GetFormState) => (state: State) => FormData;
……应该是……
export type DataSelector = <FormData = {}, State = {}>(formName: string, getFormState?: GetFormState) => (state: State) => FormData;
...(=
右侧的通用参数)经过此更改,现在有效:
const name = getFormValues<FormFields>('my-form')(state)?.name;
已打开 PR:https://github.com/DefinitelyTyped/DefinitelyTyped/pull/49896
这里的问题是 getFormValues
不是通用函数,因此没有直接的方法可以将其用于您的目的。类型 DataSelector
与 DataSelector<{}, {}>
相同,因为 DataSelector
的定义使用 type parameter defaults。所以 getFormValues
本质上有以下类型:
declare const getFormValues: (
formName: string, getFormState?: GetFormState
) => (state: {}) => {};
里面没有通用的东西了。如果你调用 getFormValues()
它 return 是一个 (state: {}) => {}
类型的函数,它接受(几乎)任何东西和 returns {}
,一个没有已知属性的对象类型.
我不太确定 DataSelector
的预期用途是什么,也不确定 getFormValues()
是如何实现的,所以以下只是我可能用来获得适合您的内容的类型具体示例代码。
如果您希望 getFormValues
自身 成为泛型函数,则需要将泛型类型参数从 DataSelector
type 声明和 call signature,像这样:
type GenericDataSelector = <FormData = {}, State = {}>(
formName: string, getFormState?: GetFormState
) => (state: State) => FormData;
然后让 getFormValues
成为 的值 类型:
const getFormValuesGeneric = getFormValues as GenericDataSelector;
这会给你你想要的行为,我认为:
const nameOkay = getFormValuesGeneric<FormFields>('my-form')(state).name;
这行得通,尽管我对没有类型参数推理站点的泛型函数有点怀疑。 GenericDataSelector
类型的调用签名在两个参数中是通用的,这两个参数都没有出现在调用签名的参数中...它们只出现在 return 类型中。
这意味着如果我调用 getFormValuesGeneric("something")
,编译器不知道如何推断 State
和 FormData
应该是什么,它最终默认为 {}
和 {}
。如果你想要不同的东西,你需要手动指定它,比如 getFormValuesGeneric<MyFormData, MyState>("something")
.
这行得通,但你最终会说 getFormValuesGeneric<FormData1, State1>("something")
return 是一个 (state: State1) => FormData1
类型的函数,而 getFormValuesGeneric<FormData2, State2>("something")
return 是一个类型的函数(state: State2) => FormData2
类型的函数。但是当然在运行时类型系统是 erased,所以这两个都是 getFormValuesGeneric("something")
。两个相同的调用如何 return 两种不同的函数类型取决于已被删除的内容?他们不能,真的。
意思是至多 <FormData1, State1>
或<FormData2, State2>
之一是getFormValuesGeneric("something")
的正确选择...并选择正确的我想,是编写调用该函数的 TS 代码的人的责任。但是在那种情况下,这与使用 type assertion (您所谓的“演员”)之间没有太大区别;他们都不保证任何类型的安全。
据推测,传入的 formName
参数的值与 FormData
和 State
的正确规范之间存在某种关系,但这对编译器来说是未知的。可以想象重写类型,以便编译器能够跟踪此映射,但我认为这超出了这个问题的范围。
从所有这些中得出的结论是 在使用其参数无法从任何东西合理推断出的泛型函数时要小心。
根据 redux-form
typings 的定义:
export type DataSelector<FormData = {}, State = {}> = (formName: string, getFormState?: GetFormState) => (state: State) => FormData;
export const getFormValues: DataSelector;
请注意 DataSelector
有两个类型参数。如果我调用 getFormValues
,这是一个 const
函数,我该如何提供类型参数?
type FormFields = { name: string };
// No type argument specified so: Property 'name' does not exist on type '{}'.
const name = getFormValues('my-form')(state)?.name;
// I could cast it, but no thank you ...
const name = (getFormValues('my-form')(state) as any as FormFields)?.name;
// Need to supply `FormFields` as the generic argument for `FormData`, but how? This doesn't work ...
const name = getFormValues<FormFields>('my-form')(state)?.name;
- 我能否以某种方式为
const
函数指定通用参数? - 打字有误吗?如何纠正它们?
更新: 这种情况下的输入不正确。而不是...
export type DataSelector<FormData = {}, State = {}> = (formName: string, getFormState?: GetFormState) => (state: State) => FormData;
……应该是……
export type DataSelector = <FormData = {}, State = {}>(formName: string, getFormState?: GetFormState) => (state: State) => FormData;
...(=
右侧的通用参数)经过此更改,现在有效:
const name = getFormValues<FormFields>('my-form')(state)?.name;
已打开 PR:https://github.com/DefinitelyTyped/DefinitelyTyped/pull/49896
这里的问题是 getFormValues
不是通用函数,因此没有直接的方法可以将其用于您的目的。类型 DataSelector
与 DataSelector<{}, {}>
相同,因为 DataSelector
的定义使用 type parameter defaults。所以 getFormValues
本质上有以下类型:
declare const getFormValues: (
formName: string, getFormState?: GetFormState
) => (state: {}) => {};
里面没有通用的东西了。如果你调用 getFormValues()
它 return 是一个 (state: {}) => {}
类型的函数,它接受(几乎)任何东西和 returns {}
,一个没有已知属性的对象类型.
我不太确定 DataSelector
的预期用途是什么,也不确定 getFormValues()
是如何实现的,所以以下只是我可能用来获得适合您的内容的类型具体示例代码。
如果您希望 getFormValues
自身 成为泛型函数,则需要将泛型类型参数从 DataSelector
type 声明和 call signature,像这样:
type GenericDataSelector = <FormData = {}, State = {}>(
formName: string, getFormState?: GetFormState
) => (state: State) => FormData;
然后让 getFormValues
成为 的值 类型:
const getFormValuesGeneric = getFormValues as GenericDataSelector;
这会给你你想要的行为,我认为:
const nameOkay = getFormValuesGeneric<FormFields>('my-form')(state).name;
这行得通,尽管我对没有类型参数推理站点的泛型函数有点怀疑。 GenericDataSelector
类型的调用签名在两个参数中是通用的,这两个参数都没有出现在调用签名的参数中...它们只出现在 return 类型中。
这意味着如果我调用 getFormValuesGeneric("something")
,编译器不知道如何推断 State
和 FormData
应该是什么,它最终默认为 {}
和 {}
。如果你想要不同的东西,你需要手动指定它,比如 getFormValuesGeneric<MyFormData, MyState>("something")
.
这行得通,但你最终会说 getFormValuesGeneric<FormData1, State1>("something")
return 是一个 (state: State1) => FormData1
类型的函数,而 getFormValuesGeneric<FormData2, State2>("something")
return 是一个类型的函数(state: State2) => FormData2
类型的函数。但是当然在运行时类型系统是 erased,所以这两个都是 getFormValuesGeneric("something")
。两个相同的调用如何 return 两种不同的函数类型取决于已被删除的内容?他们不能,真的。
意思是至多 <FormData1, State1>
或<FormData2, State2>
之一是getFormValuesGeneric("something")
的正确选择...并选择正确的我想,是编写调用该函数的 TS 代码的人的责任。但是在那种情况下,这与使用 type assertion (您所谓的“演员”)之间没有太大区别;他们都不保证任何类型的安全。
据推测,传入的 formName
参数的值与 FormData
和 State
的正确规范之间存在某种关系,但这对编译器来说是未知的。可以想象重写类型,以便编译器能够跟踪此映射,但我认为这超出了这个问题的范围。
从所有这些中得出的结论是 在使用其参数无法从任何东西合理推断出的泛型函数时要小心。