TypeScript——泛型(函数泛型、模板类型可以是多个、泛型的错误、泛型函数变量、泛型函数类型接口、泛型类1、泛型类2、泛型约束、泛型参数的默认类型)、声明文件、Vue3.0集成ts

目录

一、泛型

1、 函数泛型

2 模板类型可以是多个

3 泛型的错误

4 泛型函数变量

5 泛型函数类型接口

6 泛型类1

7 泛型类2

8 泛型约束

9 泛型参数的默认类型

二、声明文件

三、Vue3.0集成ts


一、泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。。

1、 函数泛型

<T>表示定义模板类型,(arg: T): T 表示参数和返回值类型都是同一个类型,
具体T是什么类型就实参决定

function a<T>(arg: T): T {
  return arg;
}
let r1 = a(100);//T的类型是number
let r2 = a("小王");//T的类型是string
console.log(r1, r2);

匿名函数和箭头函数泛型语法

//匿名函数
let a = function <T>(arg: T): T {
  return arg;
}
//箭头函数
let a = <T>(arg: T):T =>{
  return arg;
}

我们来实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:

function createArray<T123>(len: number, value: T123): T123[] {
    let arr: any[] = [];
    for (let j: number = 0; j < len; j++) {
        arr.push(value);
    }
    return arr;
}

console.log(createArray<string>(5, 'h'));
console.log(createArray(5, 0o700));

interface dataType {
    id: number;
    title: string;
    cover: string;
    tags: string[]
}

console.log(createArray<dataType>(5, {
    id: 23,
    title: '今天星期天',
    cover: 'http:///7001.png',
    tags: ['创意', '星期天', '线上']
}));

2 模板类型可以是多个

function a<T1, T2>(a:string, b:T1, c:T2): T2 {
       return c;
}
a("纟", 100, true)
function a<T1, T2>(a:string, b:T1, c:T2): string {
       return "小王";
}
let a = function<T1, T2>(a:string, b:T1, c:T2): T2 {
       return c;
}
let a = <T1, T2>(a:string, b:T1, c:T2): T2 => {
       return c;
}
function change<T1, T2>(tuple: [T1, T2]): [T2, T1] {

3 泛型的错误

function a(a:T1, b:T2): T1 {
   let r = a + b;//编译报错,因为编译器不知道T1和T2是什么类型,所以不确定是否能进行 + 运算
   return r;
}
let r = a("小王", 100);
console.log(r);
function a(a:T1): T1 {
   return a+100;//编译报错,因为编译器不知道T1是什么类型,所以不确定是否能进行 + 100
}
function loggingIdentity(arg: T): T {
    console.log(arg.length) //编译报错,因为编译器不知道T1是什么类型,所以不确定是否有属性length
    return arg
}

4 泛型函数变量

> ​    函数的变量类型也可以使用泛型

function identity<T>(arg: T): T {
    return arg;
}

interface IM {
  <x>(arg: x):x
}
let x:IM = identity;//


let myIdentity1: <U>(arg:U)=>U = identity;
let myIdentity2: {<U>(arg:U):U} = identity;

5 泛型函数类型接口

> (1)泛型函数类型接口1

function identity<T>(arg: T): T {
	console.log("identity")
    return arg;
}
//泛型函数类型接口1, 其中的T可以改为其它自定我,不必与函数中T相同
interface GenericIdentityFn1 {
    <T>(arg: T): T;
}
//值也必须是有泛型的函数
let myIdentity: GenericIdentityFn1 = identity;
//<string>决定了参数只能使用string
myIdentity<string>("sddssd"); 
//<number>决定了参数只能使用number
myIdentity<number>(234);

(2)泛型类函数型接口2

//泛型类函数型接口2
interface GenericIdentityFn2<T> {
    (arg: T): T;
}
//<number>决定了参数只能使用number
let myIdentity2: GenericIdentityFn2<number> = identity;
myIdentity2(234); 

//<string>决定了参数只能使用string
let myIdentity3: GenericIdentityFn2<string> = identity;
myIdentity3("小王"); 
console.log(r);

6 泛型类1

(1)新new出对象是{ },其中无成员

(2)对象中只能全部或部分实现类中声明好的成员,不能增加其它成员

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
// 或 yGenericNumber.add = function(x:number, y:number) { return x + y; };
let r = myGenericNumber.add(1, 22);
console.log(r);
//myGenericNumber.sex = ‘男’; 错,因为类中没有声明sex


let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "fds";
stringNumeric.add = function(x, y) { return x + y; };
let r2 = stringNumeric.add("1", "22");
console.log(r2);

7 泛型类2

new出的对象已经具体类中的成员

class A<T> {
    a:T;
	  show(a:T, b:T) {
				console.log(a, b);
	  }
}
let a1 = new A<string>();
a1.show("fsd","fsd")

let a2 = new A<number>();
a2.show(123,444)

let p2:A<string>;
p2=new A<string>()
p2.show("hello","ts")

//下面代码也不会报错,T不生效
let a3 = new A();
a3.show(444,"555");

8 泛型约束

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法.

> <T extends IA> 要求T类型数据至少有IA中声明的成员

interface IA {
    length: number;
}
//要求T类型数据有length属性
function m1<T extends IA>(arg: T): T {
    console.log(arg.length);   
    return arg;
}
let r;
r = m1("小王");//"小王"有length属性
console.log(r);//2


r = m1({length: 10, value: 3});//{length: 10, value: 3}有length属性
console.log(r);//10
interface IA {
    length: number;
	  value: number;
}
//要求T有属性length和value
function m1<T extends IA>(arg: T): T {
    console.log(arg.length, arg.value);   
    return arg;
}
m1({length: 10, value: 3, age:30});

以上泛型约束示例仅仅是函数中使用,实计上也可以使用于其它使用泛型的地方,看看下面的示例吧

class Person {
	name:string;
	sex:string;
	constructor(name, sex) {
		this.name = name;
		this.sex = sex;
	}
	show() {
		console.log(this.name, this.sex);
	}
}

class Stu<T> {
	show(p:T) {
		console.log(p);
        p.show();//有错
 	}
}
let stu = new Stu<Person>();
let p = new Person("小王", '男');
stu.show(p);

以下示例有一个问题,p.show()会出错, 如果改为下面的泛型约束就可以解决该类问题

class Person {
	name:string;
	sex:string;
	constructor(name, sex) {
		this.name = name;
		this.sex = sex;
	}
	show() {
		console.log(this.name, this.sex);
	}
}

class Stu<T extends Person> {
	show(p:T) {
		console.log(p);
		p.show();
	}
}
let stu = new Stu<Person>();
stu.show()
let p = new Person("小王", '男');
stu.show(p);

**多个类型参数之间也可以互相约束**:

function copyObj<T extends U, U>(target: T, source: U): T {
    for (const k in source) {
        target[k] = (<T>source)[k];
    }
    return target;
}
let x123 = {a:1, b:2, c:3};
const source1 = {a:1, b:2, c:3};

copyObj(x123, source1);
console.log(x123);

9 泛型参数的默认类型

我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。

function createArray<T = string>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}

二、声明文件

当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。

假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过 <script> 标签引入 jQuery,然后就可以使用全局变量 $ 或 jQuery 了。
我们通常这样获取一个 id 是 foo 的元素:
$('#foo');
// or
jQuery('#foo');

但是在 ts 中,编译器并不知道 $ 或 jQuery 是什么东西:
jQuery('#foo');
// ERROR: Cannot find name 'jQuery'.

这时,我们需要使用 declare var 来定义它的类型
declare var jQuery: (selector: string) => any;
jQuery('#foo');

什么是声明文件
通常我们会把声明语句放到一个单独的文件(jQuery.d.ts)中,这就是声明文件
**声明文件必须以 .d.ts 为后缀**

// src/jQuery.d.ts
declare var jQuery: (selector: string) => any;

// src/index.ts
jQuery('#foo');

第三方声明文件
jQuery 的声明文件不需要我们定义了,社区已经帮我们定义好了
我们可以直接下载下来使用,但是更推荐的是使用 @types 统一管理第三方库的声明文件。
@types 的使用方式很简单,直接用 npm 安装对应的声明模块即可,以 jQuery 举例
npm  install  @types/jquery --save-dev

三、Vue3.0集成ts

Vue写ts语言,不用关心转换语法问题,脚手架已经集成了ts-loader,进行转换

1、项目文件夹 -> cmd -> npm init vite +app(项目名字)

2、选择:vue    ts         然后   cd app         npm 

猜你喜欢

转载自blog.csdn.net/qq_52301431/article/details/127051461