首页 > 其他分享 >TypeScript:泛型

TypeScript:泛型

时间:2022-09-26 20:14:22浏览次数:45  
标签:TypeScript return log let arg 泛型 console

什么是泛型

泛型(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] {
    return  [tuple[1], tuple[0]];
}

 

 

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)
​
//下面代码也不会报错,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;
}

 

 

标签:TypeScript,return,log,let,arg,泛型,console
From: https://www.cnblogs.com/LIXI-/p/16732202.html

相关文章

  • TypeScript:类的类型变量
    classPerson{//脱衣服privatedisrobe(){//.....}//穿衣服privatedress(){//.....}//洗操publictak......
  • TypeScript:函数
    接口中使用函数接口可以描述函数类型;为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里面的每个参......
  • TypeScript:类
    一、概念简单认知类是现实世界或思维世界中的实体在计算机中的反映,它将数据(属性)以及这些数据上的操作(方法)封装在一起。对象是具有类类型的变量。类和对象是面向对象......
  • TypeScript:类型断言
    什么是类型断言有些时候,我们需要做一些“自己比编译器更清楚的知道自己在做什么”,这个时候就用到断言,告诉编译器:没错,就是这样的,就是要这么干。编译器也就假设:嗯,这个程序员......
  • TypeScript:运行环境搭建
    环境搭建1、安装node(16版本)2、全局安装TypeScript指令:npmi-gtypescript3、查看版本指令:tsc-v4.创建tsconfig.js文件指令:tsc--init 文件:{"c......
  • TypeScript:特征
    类型系统:1.TypeScript是静态类型: 类型系统按照「类型检查时机」来分类,可以分为动态类型和静态类型。动态类型是指在运行时才会进行类型检查,这种语言的类型错误往往会......
  • TypeScript 的一些编译选项
    compilerOptionsstrict231forceConsistentCasingInFileNames231noImplicitOverride231noPropertyAccessFromIndexSignature231noImplicitRe......
  • YApi to TypeScript(简称 ytt)根据swagger生成api代码放入项目中
    这个工具每次执行脚本内容都会覆盖代码文件,他可以用于yapi和swagger,关于yapiapi的教程可以查看官方文档,https://fjc0k.github.io/yapi-to-typescript/handbook/这里主要......
  • TypeScript学习笔记(三)—— 编译选项、声明文件
    一、编译选项与配置文件自动编译文件编译文件时,使用-w指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。示例:tscxxx.ts-w......
  • [Typescript] Tips: Derive a union type from an object
    constfruitCounts={apple:12,banana:23}typePropUnion<TextendsRecord<PropertyKey,any>>={[KinkeyofT]:{[K2inK]:T[K2]}}[keyof......