以下通用类型之间有什么区别?
type FnWithRequiredParam<T> = (t: T) => void
type FnWithParamInferred = <T>(t: T) => void
据我了解,FnWithRequiredParam
在任何情况下都将在如果未明确给出通用类型而失败。传递通用代码(强制执行),例如FnWithRequiredParam<string>
基本上会在所有情况下都变成(t: string) => void
。
但是,我找不到FnWithParamInferred
的含义。在某些情况下,<T>
是从其使用的地方(例如Array.map)推断出来的,但以下行会引发错误:
var f: FnWithParamInferred = (a: number) => { console.log(a) }
说number
和T
不兼容。在上面的行中,T
实际上是什么?它从未被精确地声明过,并且正在与另一种类型进行比较。确定在T
之类的函数类型中定义的通用<T>(...) => ...
的规则是什么?
如果<T>
被定义为类/接口的必需泛型,例如Array<T>
,然后方法od array可以成功推断T
。但是,如果它在类/接口之外,则类型推断似乎不起作用。
答案 0 :(得分:6)
两者在定义的功能签名上有很大不同。
T
参数,并在调用函数时推断(或明确指定)T
。请考虑以下声明:
declare const fn: FnWithRequiredParam<number>
declare const genericFn: FnWithParamInferred;
// T was fixed on declaration
fn(1) // ok
fn("1") // err
// T is decded by the caller
genericFn(1) // ok T is number for this call
genericFn("1") // ok T is string for this call
genericFn<number>("1") // err T was specified as number but string was passed in
出现错误的原因是,您试图将带有number
参数的函数分配给应该接受带有{{1}的任何类型的T
参数的函数}由函数的调用者决定。只有通用函数才能满足类型T
FnWithParamInferred
我认为您真正想要的是能够从变量声明中忽略显式类型参数,并根据分配给它的值进行推断。 Typescript不支持此功能。如果为变量定义类型注释,则不会对该变量进行推断。
您可以完全省略类型注释,以使编译器推断函数类型:
var f: FnWithParamInferred = <T>(a: T) => { console.log(a) }
或者您可以定义一个通用的辅助函数来推断var f = (a: number) => { console.log(a) } // inferred as (a: number) => void
,但基于T
限制函数签名
FnWithRequiredParam