Hello World of Generics
让我们以范型的hello world:“identity方法:开始着手。identity方法是一个不论输入什么,输出都返回输入的方法。你可以把它看作和echo命令一样。
没有泛型的情况下,我们要没identity方法一个特地的类型:
function identity(arg: number): number {
return arg;
}
或者,我们可以使用any类型来描述identity方法:
function identiry(arg: number): any{
return arg;
}
虽然使用any绝对是泛型,因为它使得这个方法可以接受任何类型。但是,当这个方法返回数据的时候,我们却丢失了返回值的类型。假如我们传入的是一个number类型,我们唯一的信息就是任何的类型都有可能被返回。
相反地,我们需要一种方法,这种方法既能获取参数的类型,又能标识返回类型。这里,我们需要用到类型变量,一种特殊的变量,用于类型而不是值。
function identity<T>(arg: T): T {
return arg;
}
现在,我们已经给identity方法加了一个类型变量T。这个T允许我们获取用户提供的类型(例如:number),因为我们可以在稍后使用这个信息。这里,我们再次使用T作为返回类型。经考察,现在我们可以看到相同的类型被使用到了参数类型和返回类型。这允许我们一边传入类型信息,而在另一边传出类型信息。
我们说这个类型的identity方法是范型的,因为它适用于一系列的类型。和使用any不同,它和我们第一个使用number作为参数的方法一样精确(它不会丢失任何信息)。
一旦我们写好了identity方法,我们就可以以2种方式调用它。一种是传入所有的参数,包括类型参数:
let output = identity<string>('myString');//output的类型会是'string'
这里我们通过参数以<>而不是()围绕,显式地设置T的类型为string而作为方法调用的参数之一。
第二种方法或许是最常用的方法。这里我们使用类型参数推断-也就是我们想让编译器根据我们传入的参数类型来为我们推断出T的类型。
let output = identity('string');//output的类型是string
注意到我们不用显式地给尖括号(<>)里面传入类型;编译器只是查看’myString’的类型,然后把T设置为相同类型。虽然类型参数推断是一个使得我们的代码更短更可读的有用工具,但是在更复杂的例子里可能会发生编译器无法推断出类型的情况。在这种情况下,你就需要像我们在前一个例子里做的那样:显式地给类型参数传入类型。
发表回复