乐趣区

关于typescript:TypeScript-的-generic-函数

官网链接

编写一个函数,其中输出的类型与输入的类型相干,或者两个输出的类型以某种形式相干。让咱们思考一个返回数组第一个元素的函数:

function firstElement(arr: any[]) {return arr[0];
}

这个函数实现了它的工作,但可怜的是返回类型为 any。如果函数返回数组元素的类型会更好。

在 TypeScript 中,当咱们想要形容两个值之间的对应关系时,会应用泛型。咱们通过在函数签名中申明一个类型参数来做到这一点:

function firstElement<T>(arr: T[]): T {return arr[0];
}

const arr: string[] = ['1', '2', '3'];

const result = firstElement(arr);

console.log(result);

const result1:number = firstElement(arr);

TypeScript 的类型推断 – Type inference

function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] {return arr.map(func);
}

留神,下面代码的 Inout,Output 能够被 T, V 代替,然而可读性不如前者。

Type constrains – 类型束缚

咱们曾经编写了一些能够解决任何类型值的通用函数。有时咱们想关联两个值,但只能对某个值的子集进行操作。在这种状况下,咱们能够应用束缚来限度类型参数能够承受的类型品种。

让咱们编写一个函数,返回两个值中较长的一个。为此,咱们须要一个长度属性,它是一个数字。咱们通过编写 extends 子句将类型参数限度为该类型:

function longest<Type extends {length: number}>(a: Type, b: Type) {if (a.length >= b.length) {return a;} else {return b;}
}

// longerArray is of type 'number[]'
const longerArray = longest([1, 2], [1, 2, 3]);
console.log(longerArray);

// longerString is of type 'string'
const longerString = longest("alice", "bob");
console.log(longerString);

// Error! Numbers don't have a'length' property
const notOK = longest(10, 100);

最初一个函数调用会呈现编译谬误,因为 TypeScript 根本类型 number 并不存在名称为 length 的属性。

同 Java 相比,TypeScript 的类型束缚的弱小之处在于,extends 前面紧跟的不须要是 TypeScript 的 built-in type,比方本例里的:

{length: number}

意思是,只有该函数传入的类型,至多蕴含类型为 number 的 length 属性即可。

Specifying Type Arguments

TypeScript 通常能够在泛型调用中推断出预期的类型参数,但并非总是如此。例如,假如您编写了一个函数来组合两个数组:

function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {return arr1.concat(arr2);
}

编译谬误:

解决办法:应用尖括号语法,显式传入类型参数:这里 T = string | number,意思是接管 string 或者 number 类型均可。

编写 generic 函数的最佳实际

编写泛型函数很乏味,而且很容易被类型参数冲昏头脑。有太多类型参数或在不须要它们的中央应用束缚会使推理不那么胜利,使函数的调用者感到丧气。

最佳实际 1 – Push Type Parameters Down

function firstElement1<Type>(arr: Type[]) {return arr[0];
}

function firstElement2<Type extends any[]>(arr: Type) {return arr[0];
}

// a: number (good)
const a = firstElement1([1, 2, 3]);
// b: any (bad)
const b = firstElement2([1, 2, 3]);

乍一看,两种办法仿佛雷同,但 firstElement1 是编写此函数的更好办法。它的推断返回类型是 Type,但 firstElement2 的推断返回类型是 any,因为 TypeScript 必须应用束缚类型解析 arr[0] 表达式,而不是在调用期间“期待”解析元素。

最佳实际 2- Use Fewer Type Parameters

function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {return arr.filter(func);
}

function filter2<Type, Func extends (arg: Type) => boolean>(arr: Type[],
  func: Func
): Type[] {return arr.filter(func);
}

咱们创立了一个不关联两个值的类型参数 Func。这总是一个危险信号,因为这意味着想要指定类型参数的调用者必须平白无故地手动指定一个额定的类型参数。Func 不会做任何事件,只会让函数更难浏览和推理!

最佳实际 3 – Type Parameters Should Appear Twice

function greet<Str extends string>(s: Str) {console.log("Hello," + s);
}

greet("world");

这个例子里,Str 只呈现了一次,因而基本毫无必要。

能够简写成:

function greet(s: string) {console.log("Hello," + s);
}

请记住,类型参数用于关联多个值的类型。如果一个类型参数在函数签名中只应用一次,它就没有任何关系。

更多 Jerry 的原创文章,尽在:” 汪子熙 ”:

退出移动版