TypeScript---Ts中的泛型总结

1、定义

【泛型】指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。当想让函数/接口/类用于多种类型同时保证类型安全时,可以使用泛型。

2、泛型函数

function getValue<T>(value: T): T {
    return value
}
getValue<number>(1)//或者id(1) ts具有类型推断
getValue<string>('a')
getValue<boolean>(false)
getValue(100)//类型推断为字面量类型100

【多个泛型参数的函数】一个函数可以定义多个泛型参数

function getArr<K, V>(value1: K, value2: V): [K, V] {
    return [value1, value2]
}

const arr = getArr<number, string>(123, "哈哈哈")
console.log(arr) //[123,"哈哈哈"]
console.log(arr[0].toFixed(2), arr[1].split("")) //123.00  ["哈","哈","哈"]

3、泛型接口

【泛型接口】在定义接口时, 为接口中的属性或方法定义泛型类型在使用接口时, 再指定具体的泛型类型


interface IdFunc<T> {
    id: (value: T) => T
    ids: () => T[]
}

let obj1: IdFunc<number> = {
    id(value) { return value },
    ids() { return [1, 3] }
}
//数组是泛型接口实现的
const s1 = [1, 2, 3]
s1.forEach(item => { })
const s2 = ['a', 'b']
s2.forEach(item => { })
interface IBaseCRUD<T>{
    data:Array<T>
    add:(t:T)=>T
    getUserId:(id:number)=>T
} 

class User{
    id?:number
    name:string
    age:number
    constructor(name:string,age:number){
        this.name=name
        this.age=age
    }
}

class UserCRUD implements IBaseCRUD<User>{
    data:Array<User>=[]
    add(user:User):User{
    user.id=Date.now()+Math.random()
    // 把用戶對象添加到data数组中
    this.data.push(user)
    return user
     }

    getUserId(id:number):any{
        console.log("输出this.data",this.data)
        console.log(this.data.find(user=>user.id===id));
        return this.data.find(user=>user.id===id)
    }
}
  
const userCRUD:UserCRUD=new UserCRUD()
userCRUD.add(new User("小明",20))
let {id}=userCRUD.add(new User("小方",30))
userCRUD.add(new User("布丁",25))
userCRUD.add(new User("小米",22))

console.log(userCRUD.data);
console.log(id);
typeof id =='number'?console.log("查找成功",userCRUD.getUserId(id)):console.log("查找失敗");

4、泛型类

【泛型类】定义一个类,类中的属性值的类型是不确定的,方法中的参数及返回值的类型也是不确定的。在定义类时, 为类中的属性或方法定义泛型类型。 在创建类的实例时, 再指定特定的泛型类型

class Persons<T> {
    private value: T;
    constructor(value: T) {
        this.value = value;
    }

    getValue(): T {
        return this.value;
    }
}

const ps1 = new Persons<string>("小美");
console.log(ps1.getValue());


const ps2 = new Persons<number[]>([1, 2, 3]);
console.log(ps2.getValue());

5、泛型约束

如果直接对一个泛型参数取length属性,会报错,因为这个泛型根本就不知道它有这个属性。定义一个接口,用来约束将来的某个类型中必须要有length这个属性

interface ILength {
    length: number
}
//使用extends关键字为泛型添加约束
function getLength<T extends ILength>(value: T): number {
    return value.length
}
console.log(getLength("I am a student")) //14



//keyof关键字获取对象所有键的集合
function getProp<T, k extends keyof T>(obj: T, key: k) {
    return obj[key]
}
getProp({ name: "maidu", age: 11 }, 'name')

6、泛型工具类型

Partial-可选属性;readonly-只读属性;Pick<Type,keys> 获取某type中的某些属性;

Record<keys,Type>构造一个对象类型,属性键为keys2,属性类型为Type。

//Partial-可选属性
interface IProps {
    id: string
    title: string
    children: number[]
}
type IPartialProps = Partial<IProps>
const a: IPartialProps = {} //可选属性0-2个

//readonly-只读属性
type IReadonlyProps = Readonly<IProps>
let a2: IReadonlyProps = { id: "1", title: "", children: [1] }
// a2.id = "3"//错误


//Pick<Type,keys> 获取某type中的某些属性
type IPickProps = Pick<IProps, 'id' | 'title'>

//Record<keys,Type>构造一个对象类型,属性键为keys2,属性类型为Type
type IRecord = Record<'a' | 'b' | 'c', string[]>
let a3: IRecord = { a: ['1'], b: ["we"], c: ["3"] }

7、索引签名类型

interface IAnyObj {
    [key: string]: number
    // [propName: string]: any;
}

//使用索引签名实现数组,通过索引访问数组
interface IMyArray<T> {
    [index: number]: T
}
let arr: IMyArray<number> = [1, 22, 3]
arr[0]

8、映射类型

//类型映射只能使用在类型别名type中,不能在接口interface中使用
type PropsKeys = 'x' | 'y' | 'z'
type Types = { [Key in PropsKeys]: number } //等价于{x:number;y:number;z:number}

type PropsObj = { a: number; b: string; c: boolean }
type Type1 = { [key in keyof PropsObj]: number }

//Partial实现是基于映射类型
type MyPartial<T> = {
    [P in keyof T]?: T[P];
};


//索引查询类型
type Type2 = PropsObj['a']
type Type3 = PropsObj['a' | 'b']//同时查询多个索引类型
type Type4 = PropsObj[keyof PropsObj]//同时查询多个索引类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Ts 泛型在函数的使用举例:比如我们有一个函数,它可以接收任意类型的参数,但是我们又希望在函数内部对这些参数进行一些操作,那么我们就可以使用泛型来实现这个功能。例如: function identity<T>(arg: T): T { return arg; } 这个函数接收一个泛型参数 T,它可以是任意类型。在函数内部,我们直接返回这个参数,这样就可以实现对任意类型的参数进行操作了。 ### 回答2: TypeScript (TS) 是一种静态类型语言,它引入了泛型概念,用于在函数进行通用类型的处理。下面是一个使用泛型的函数示例: ```typescript function reverseArray<T>(arr: T[]): T[] { return arr.reverse(); } const numbers = [1, 2, 3, 4, 5]; const reversedNumbers = reverseArray(numbers); console.log(reversedNumbers); // [5, 4, 3, 2, 1] const strings = ['Hello', 'World']; const reversedStrings = reverseArray(strings); console.log(reversedStrings); // ['World', 'Hello'] ``` 上述示例,函数 `reverseArray` 使用了泛型 `<T>`,表示该函数可以接受通用类型 `T` 的数组作为参数,并返回相同类型的数组。在函数体内,首先调用了数组的 `reverse` 方法,然后将结果返回。 在代码调用 `reverseArray` 函数时,可以传入不同类型的数组参数。比如,`numbers` 是一个整数数组,`strings` 是一个字符串数组。通过使用泛型,我们可以方便地处理这些不同类型的数组,并获得相应的结果。 在编译阶段,TypeScript 会根据实际传入的参数类型进行类型推导,确保传入的参数类型和返回值类型一致,从而提供编译时的类型检查。这样可以避免传入错误类型的参数导致运行时错误的问题。 总之,通过使用泛型,我们可以在函数编写通用的代码,以适应不同类型的数据,并且在编译阶段进行类型检查,提高代码的可靠性和可维护性。 ### 回答3: 泛型在函数的使用可以提供更加灵活和通用的编程方式,以下是一个关于泛型在函数的使用举例: 举例我们有一个函数 `findMax`,用于找到数组的最大值。如果我们只是针对具体的数值类型进行编写,那么函数的重用性会受到限制。但是通过使用泛型,我们可以编写一个能够适用于不同类型的数组的函数。 ```java public static <T extends Comparable<T>> T findMax(T[] array) { T max = array[0]; for (int i = 1; i < array.length; i++) { if (array[i].compareTo(max) > 0) { max = array[i]; } } return max; } ``` 在这个例子,使用了 `<T extends Comparable<T>>` 这样的语法来声明泛型 `T`,并限制了 `T` 的类型必须是实现了 `Comparable` 接口的类型,这样我们就可以使用 `compareTo` 方法来比较不同类型的对象。 通过使用泛型,我们可以在调用这个函数时传入不同类型的数组,例如 `Integer[]`、`Double[]` 或者自定义的类数组,而不需要针对每种类型编写不同的函数。 ```java Integer[] integers = {1, 2, 3, 4, 5}; Double[] doubles = {1.5, 2.3, 0.9, 4.7}; String[] strings = {"apple", "banana", "orange"}; System.out.println(findMax(integers)); // 输出:5 System.out.println(findMax(doubles)); // 输出:4.7 System.out.println(findMax(strings)); // 输出:orange ``` 通过这个例子,我们可以看到泛型在函数的使用,使得我们能够更加灵活地处理不同类型的数据,提高了代码的可重用性和通用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值