根底阐明
如果咱们须要定义一个函数,一个入参和一个返回值,入参和返回值类型须要保持一致,怎么办?
比方规定类型都是字符串,那么:
function doit(arg: string): string { return arg;}
能够看进去,类型这里写死成string了,那类型可不可以像参数一样定义成变量传递进来?当然能够,咱们革新一下代码:
function doit<T>(arg: T): T { return arg;}
这里通过<T>定义了一个类型变量T,而这个T具体是什么类型,应用的时候用户传递即可:
let result: string = doit<string>("我是一个字符串");
事实上,编译器通过查看arg的值的类型,能够推断出T示意什么类型,因而,大部分状况下,上述代码能够简化一下:
let result: string = doit("我是一个字符串");
泛型类型
function doit<T>(arg: T): T { return arg;}let myDoit: Function = doit;
咱们想把函数doit赋值给变量myDoit,咱们定义myDoit的类型是Function,那么,可不可以明确一下myDoit的类型细节?答案是必定的:
let myDoit: <T>(arg: T) => T = doit;
或
let myDoit: { <T>(arg: T): T } = doit;
泛型接口
聪慧的是必定能够想到,咱们还能够定义一个接口:
interface DoitFnType { <T>(arg: T): T;} let myDoit: DoitFnType = doit;
类型锁定
当初有一个状况,咱们在给myDoit赋值的是,曾经明确了类型T的理论值肯定是string,那么,就能够这样改变:
interface DoitFnType<T> { (arg: T): T;} let myDoit: DoitFnType<string> = doit;
泛型类
也非常简单,咱们间接举个例子:
class Dog<T>{ info: T; setInfo(info: T): void { this.info = info; }}
创立的时候也是相似的:
let dog = new Dog<string>();
那么,setInfo函数就只能传递字符串类型:
dog.setInfo('小狗');
而上面的写法就是谬误的:
// Argument of type 'boolean' is not assignable to parameter of type 'string'. dog.setInfo(true);
舒适提醒:类的动态属性不能应用这个泛型类型,为什么?因为类型值是new的时候设置的,动态的时候基本不存在。
泛型束缚
function doit<T>(arg: T) { // Property 'length' does not exist on type 'T'. console.log(arg.length);}
在下面的代码中,咱们心愿打印arg的属性length,尽管类型T待定,可是咱们明确晓得传递的数据肯定会有length属性。可是,编译器并不能证实类型T蕴含lenght属性,因而会提醒谬误。
怎么办?咱们把代码革新一下:
interface ArgType { length: number;}function doit<T extends ArgType>(arg: T) { console.log(arg.length);}
当初这个泛型被束缚了,传递的参数必须蕴含length属性,比方字符串是能够的:
doit("小花");
而数字就不行:
// Argument of type 'number' is not assignable to parameter of type 'ArgType'.doit(10);