const sum = <T>( array: readonly T[], mapper: (item: T) => number ): number => array.reduce( (acc, item) => acc + mapper(item), 0 );让我们看一下类型定义。此函数包含:
2.映射器函数:(item: T) => number
type Mapper<T> = (item: T) => number;让我们想象一个用例:
interface YouTubeVideo { name: string; views: number; } const youTubeVideos: YouTubeVideo[] = [ { // 堆代码 duidaima.com name: "My favorite cheese", views: 100, }, { name: "My second favorite cheese (you won't believe it)", views: 67, }, ]; const mapper: Mapper<YouTubeVideo> = (video) => { return video.views; }; const result = sum(youTubeVideos, mapper); // 167三.关于什么是函数?
const sum = <T>( array: readonly T[], mapper: Function ): number => array.reduce( (acc, item) => acc + mapper(item), 0 );这个关键字基本上代表“任何函数”。这意味着从技术上讲可以 sum 接收任何函数。当在 中使用 sum 时,我们失去了很多 (item: T) => number 提供的安全性:
const result = sum(youTubeVideos, (item) => { // Parameter 'item' implicitly has an 'any' type. // We can return anything from here, not just // a number! return item.name; });TypeScript 现在无法推断应该是什么 item ,或者我们的mapper函数应该返回什么。这里的教训是“不要使用 Function ” - 总有一个更具体的选项可用。
export type Parameters< T extends (...args: any) => any > = T extends (...args: infer P) => any ? P : never; export type ReturnType< T extends (...args: any) => any > = T extends (...args: any) => infer R ? R : any;您会注意到这两种实用程序类型使用相同的约束:(...args: any) => any 。
const wrapFuncWithNoArgs = (func: () => any) => { try { return func(); } catch (e) {} }; wrapFuncWithNoArgs((a: string) => {}); > Argument of type '(a: string) => void' is not assignable to parameter of type '() => any'. > Target signature provides too few arguments. Expected 1 or more, but got 0.六.总结
const youTubeVideos = [ { name: "My favorite cheese", views: 100 }, { name: "My second favorite cheese (you won't believe it)", views: 67, }, ]; const result = sum(youTubeVideos, (video) => { return video.views; }); // 167事实上,我们已经舍弃了所有类型声明,但 video仍旧被推断为 { name: string; views: number } 。这是可能的,因为我们的函数定义的特殊性:(item: T) => number 。