class Clock implements ClockInterface {
currentTime: Date;
constructor(h: number, m: number) { }
}
当然,也可以在接口中描述一个方法,在类里实现它,如同下面的setTime方法一样:
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
============================================================
简单的说,一个良好的API,不仅要考虑支持当前的数据类型,也要能支持未来的数据类型,因此,通过泛型来创建可以重用的组件,也就是一个组件支持多种类型的数据,例如:
function person(arg: string): string {
return arg;
}
console.log(person(‘Oliver’))
定义了一个person,参数类型是字符串,也许当前我们是通过名字来命名的,所以使用string,但是将来也许就不是名字是ID来调用了,因此如果写死了string,那么重用性就会很差,未来将不能使用,因此就需要使用泛型,支持多种类型;
所以说到底,泛型也是一种类型,只是这种类型很抽象,需要到使用的时候才知道,而不是和string,number这种一开始就已经定义好了的类型一样
泛型的好处就是可以限定输入和返回是相同的类型,有人可能会说any,但是相比类型设置any,any做不到返回一定和输入的类型相同,比如:
function person(arg: any): any {
return arg;
}
输入的arg可以是数字类型,但是返回值的类型可以是字符串,那么输入的类型则和返回的类型不相同了,因此就可以使用泛型;
function person(arg:T):T{
return arg
}
我们给函数person设置了一个泛型,并且限定了参数arg的类型也是T,返回值的类型也是T,那么至少我们知道,输入和输出都是类型T,当然,此时的T没有具体的类型,接着就是我们使用了;
泛型的使用一种有两种方式:
第一种:
let output = identity(“myString”);
我们明确了,那么根据规则我们可以知道,输入必须是string类型,输出也肯定是string类型;
第二种:
let output = identity(“myString”);
这种我们可能更常用一点,原因很简单,少写了代码,但是功能是完全一摸一样的,TS的编译器会自动的去识别参数,因为通过设置泛型,我们确定了输入输出必须一致,那么此时输入的是字符串类型,那么输出必然的也必须是字符串类型;
当然,泛型也是可以在接口中使用的,先看一个示例:
function student(arg:T):T{
return arg
}
// 定义了一个接口GenericPerson
interface GenericPerson{
// 定义了一个函数
// :代表泛型
// (arg:T):参数也是泛型
// :T :返回值也是泛型T
(arg:T):T
}
// 定义了一个变量person,遵循的规则集是接口GenericPerson
let person:GenericPerson = function (arg) {
return arg
}
let person2:GenericPerson = student;
console.log(person(12333)) // 指定了泛型为number类型
console.log(person2(132333)) // 不指定类型,类型由ts自己判断
另外,通过 extends 可以为泛型增加约束,限定泛型的类型或者必须包含一定的属性,例子如下:
// 限定泛型,必须包含length属性,并且值必须是number类型或者是string类型
function student<T extends { length:number | string} >(arg:T):T{
return arg
}
let obj = {
length:10
}
console.log(student(obj))
// 限定了泛型必须是数字类型或者是字符串类型
function student<T extends number | string >(arg:T):T{
return arg
}
let obj = ‘10’
console.log(student(obj))
而在类中使用泛型,例子如下
// 在类名后面使用泛型
class CountNumber{
num1:T; // num1的类型是泛型T
num2:T = 1; // num2的类型是泛型T,默认值是1
constructor(num1:T,num2:T){
this.num1 = num1;
this.num2 = num2;
}
countNum():number{
// +号是ts提供的一种解决方案,不然会报错
return +this.num1 * +this.num2
}
}
// 可以限定泛型的类型,也可以不限定
const number = new CountNumber(10,20);
// 不限定
const number = new CountNumber(10,20);
console.log(number.countNum())
// 即使限定类型是字符串,但是通过“+”号,也可以转成数字,从而进行计算
const number2 = new CountNumber(‘10’,‘20’);
console.log(number2.countNum()) //200
当然,在类中的泛型也可以进行约束的,例如:
// 在类名后面使用泛型,传递过来的类型必须是数字类型
class CountNumber{
num1:T; // num1的类型是泛型T
num2:T = 1; // num2的类型是泛型T,默认值是1
constructor(num1:T,num2:T){
this.num1 = num1;
this.num2 = num2;
}
countNum():number{
// +号是ts提供的一种解决方案,不然会报错
return +this.num1 * +this.num2
}
}
react和vue的比较
相同
1)vitual dom
2)组件化
3)props,单一数据流
不同点
1)react是jsx和模板;(jsx可以进行更多的js逻辑和操作)
2)状态管理(react)
3)对象属性(vue)
4)vue:view——medol之间双向绑定
5)vue:组件之间的通信(props,callback,emit)
方案,不然会报错
return +this.num1 * +this.num2
}
}
react和vue的比较
相同
1)vitual dom
2)组件化
3)props,单一数据流
不同点
1)react是jsx和模板;(jsx可以进行更多的js逻辑和操作)
2)状态管理(react)
3)对象属性(vue)
4)vue:view——medol之间双向绑定
5)vue:组件之间的通信(props,callback,emit)
[外链图片转存中…(img-66fdidi2-1714402446707)]