泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)
只能返回string类型的数据
function getData(value:string):string{
return value;
}
需要同时返回 string类型 和number类型(代码冗余)
function getData1(value:string):string{
return value;
}
function getData2(value:number):number{
return value;
}
同时返回 string类型 和number类型 ,any可以解决这个问题
function getData(value:any):any{
return value+'hello';
}
getData(123);
getData('str');
any放弃了类型检查,传入的参数类型和返回的参数类型可以不一致
//any存在问题,传入值的类型,但无法获取返回值 的类型
function getData<T>(value:T):any{
return '2145214214';
}
getData<number>(123); //参数必须是number
getData<string>('这是一个泛型');
如果需要传入什么 返回什么。比如:传入number 类型必须返回number类型 传入 string类型必须返回string类型
泛型: 是指在定义函数/接口/类时,不预先指定具体的类型,而在使用的时候再指定类型的一种特性; 可以支持不特定的数据类型 要求:传入的参数和返回的参数一致
T表示泛型,具体什么类型是调用这个方法的时候决定的
//T 泛型变量 表示任何类型
function getData<T>(value:T):T{
return value;
}
getData<number>(123);
getData<string>('1214231');
getData<number>('2112'); /*错误的写法*/
// 是指在定义函数/接口/类时,不预先指定具体的类型,而在使用的时候再指定类型的一种特性;
//T 泛型变量 表示任何类型
function fun3<T>(name:T):T{
console.log('hello ' + name);
return name;
};
fun3<string>('abc');
//定义了泛型函数后,使用方式传入参数
// 定义多个类型
fun3<string | number>('abc');
需求:比如有个最小堆算法,需要同时支持返回数字和字符串 a - z两种类型。 通过类的泛型来实现
//下面这个只能支持数字类型
class MinClass{
public list:number[]=[];
add(num:number){
this.list.push(num)
}
min():number{
// var minNum = Math.min(...this.list)
//因为要比较数字 和 字符串,所以用下面的方法
var minNum=this.list[0];
for(var i=0;i<this.list.length;i++){
if(minNum>this.list[i]){
minNum=this.list[i];
}
}
return minNum;
}
}
var m=new MinClass();
m.add(30);
m.add(22);
m.add(6);
alert(m.min());
如何同时只是数字和 字符串的参数比较大小呢 ?
利用类的泛型
class MinClas<T> {
public list: T[] = [];
add(value: T): void {
this.list.push(value);
}
min(): T {
var minNum = this.list[0];
for (var i = 0; i < this.list.length; i++) {
if (minNum > this.list[i]) {
minNum = this.list[i];
}
}
return minNum;
}
}
//实例化类 并且制定了类的T代表的类型是number
var m1=new MinClas<number>();
m1.add(11);
m1.add(3);
m1.add(2);
alert(m1.min())
// 实例化类 并且制定了类的T代表的类型是string
var m2 = new MinClas<string>();
m2.add("b");
m2.add("k");
m2.add("v");
alert(m2.min());
//函数声明
function fun5<T>(name:T):T{
return name
}
//函数表达式
let fun6 = function<A>(name:A):A{
return name;
}
//ES6
let fun7 =<U>(name:U):U => name;
interface ConfigFn{
(value1:string,value2:string):string;
}
var setData:ConfigFn=function(value1:string,value2:string):string{
return value1+value2;
}
setData('name','张三');
如果希望能同时支持返回string,number类型接口, 上面的函数接口就达不到要求
在接口里定义泛型
interface ConfigFn{
<T>(value:T):T;
}
var getData:ConfigFn=function<T>(value:T):T{
return value;
}
getData<string>('张三');
// getData<string>(1243); //错误
interface ConfigFn<T> {
(value: T): T;
}
function getData<T>(value: T): T {
return value;
}
var myGetData: ConfigFn<string> = getData;
myGetData("20"); /*正确*/
// myGetData(20) //错误
//接口
interface Search{
<T>(a:T,b:T):boolean;
}
// 接口Search代表 有2个参数,类型为任意类型, 而且参数类型是保持一致的, 接口返回的是boolean值
// 下面是使用接口:
let f4:Search = function<T>(str1:T,str2:T):boolean{ //void无返回值
return str1==str2; //true/false
}
f4<number>(123,456)
class A2<T>{
n:T; //表示属性的类型
constructor(num:T){ //值的类型
this.n = num;
}
action(x:T):T{
return x
}
};
var a2 = new A2<string>('abc'); //实例化
a2.action('3')
把类作为参数来约束数据传入的类型
class User{
username:string | undefined;
pasword:string | undefined;
constructor(username:string,pasword:string) {
this.username = username;
this.pasword = pasword;
}
}
class MysqlDb{
allUser:any[] = [];
add(user:User):boolean{
console.log(user);
this.allUser.push(user)
return true;
}
getUsers(){
console.log(this.allUser)
}
}
var u1=new User('张三','123456');
var u2=new User('李四','123456');
var Db=new MysqlDb();
Db.add(u1);
Db.add(u2);
Db.getUsers();
数组泛型
//数组泛型 也可以使用数组泛型 Array<elemType> 来表示数组
let arr: Array<any> = [1, '1', true, 3, 5]; //number[]
定义返回值的类型T
我们在函数名后添加了 ,其中 T 用来指代任意输入的类型, 在后面的输入 value: T 和输出 Array 中即可使用了。
function createArray2<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray2<string>(3, 'x');