【5天学会TS】打卡学习Typescript的第二天

系列文章推荐:

相关文章推荐:

【5天学会TS】打卡学习Typescript的第一天-优快云博客


文章目录:

目录

系列文章推荐:

文章目录:

前言:

版本说明:

具体内容:

1.泛型的使用意义:

2.泛型的标识符

3.泛型应用

3.1 泛型函数

3.2 泛型接口

3.3 泛型类

4.泛型约束

5.泛型参数的默认类型

6.泛型的工具类型

6.1 Partial 用来构造(创建)一个类型,将 Type 的所有属性设置为可选

6.2 Readonly 用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)

6.3 Pick从 Type 中选择一组属性来构造新类型

6.4 Record 构造一个对象类型,属性键为 Keys,属性类型为 Type

最后


前言:

昨天学习了TS的数据类型,基于JS的类型有些扩展,今天重点学习泛型。泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。


版本说明:

Node.js: 18.20.4

npm:10.7.0

具体内容:

1.泛型的使用意义:

  • 代码重用: 可以编写与特定类型无关的通用代码,提高代码的复用性。
  • 类型安全: 在编译时进行类型检查,避免在运行时出现类型错误。
  • 抽象性: 允许编写更抽象和通用的代码,适应不同的数据类型和数据结构。

2.泛型的标识符

T: 代表 "Type",是最常见的泛型类型参数名

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

K, V: 用于表示键(Key)和值(Value)的泛型类型参数

interface KeyValuePair<K, V> {
    key: K;
    value: V;
}

E: 用于表示数组元素的泛型类型参数

function printArray<E>(arr: E[]): void {
    arr.forEach(item => console.log(item));
}

R: 用于表示函数返回值的泛型类型参数

function getResult<R>(value: R): R {
    return value;
}

U, V: 通常用于表示第二、第三个泛型类型参数

function combine<U, V>(first: U, second: V): string {
    return `${first} ${second}`;
}

这些标识符是约定俗成的,实际上你可以选择任何符合标识符规范的名称。

3.泛型应用

3.1 泛型函数

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

// 使用泛型函数
let result = identity<string>("Hello");
console.log(result); // 输出: Hello

let numberResult = identity<number>(42);
console.log(numberResult); // 输出: 42

3.2 泛型接口

// 基本语法
interface Pair<T, U> {
    first: T;
    second: U;
}

// 使用泛型接口
let pair: Pair<string, number> = { first: "hello", second: 42 };
console.log(pair); // 输出: { first: 'hello', second: 42 }

3.3 泛型类

// 基本语法
class Box<T> {
    private value: T;

    constructor(value: T) {
        this.value = value;
    }

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

// 使用泛型类
let stringBox = new Box<string>("TypeScript");
console.log(stringBox.getValue()); // 输出: TypeScript

4.泛型约束

在这个例子中,定义了一个泛型函数 logLength,它接受一个类型为 T 的参数,但有一个约束条件,即 T 必须实现 Lengthwise 接口,该接口要求有 length 属性。因此,可以正确调用 logLength("hello"),但不能调用 logLength(42),因为数字没有 length 属性。

// 基本语法
interface Lengthwise {
    length: number;
}

function logLength<T extends Lengthwise>(arg: T): void {
    console.log(arg.length);
}

// 正确的使用
logLength("hello"); // 输出: 5

// 错误的使用,因为数字没有 length 属性
logLength(42); // 错误

各个参数之间互相约束:

function copyFields<T extends U, U>(target: T, source: U): T {
    for (let id in source) {
        target[id] = (<T>source)[id];
    }
    return target;
}

let x = { a: 1, b: 2, c: 3, d: 4 };

copyFields(x, { b: 10, d: 20 });

指定具体类型,将类型修改为 Type[](Type 类型的数组),因为只要是数组就一定存在 length 属性

function id<T>(value:T[]):T[]{
    console.log(value.length)
    return value
}
let idfirst = id([1,2,3])
console.log(idfirst)
// 3
// [1,2,3]

添加约束,传入参数必须有length属性

interface nober{
    length:number,
}
function numberone<T extends nober>(arg:T):T{
    console.log(arg.length)
    return arg
}
let egone = numberone('happy')
console.log(egone)
// 5
// happy

5.泛型参数的默认类型

 这个例子展示了带有默认值的泛型函数。函数 defaultValue 接受一个泛型参数 T,并给它设置了默认类型为 string

// 基本语法
function defaultValue<T = string>(arg: T): T {
    return arg;
}

// 使用带默认值的泛型函数
let result1 = defaultValue("hello"); // 推断为 string 类型
let result2 = defaultValue(42);      // 推断为 number 类型

6.泛型的工具类型

6.1 Partial 用来构造(创建)一个类型,将 Type 的所有属性设置为可选

interface data1{
    id:string,
    students:number[]
}
type data2 = Partial<data1>
let p1:data1 = {
    id: 's1',
    students: [1, 2]
}     
let p2:data2 = {
    id: 's2',
    students: [1, 2, 3]
}
console.log(p1,p2)

6.2 Readonly 用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)

interface data1{
    id:string,
    students:number[]
}
type data2 = Readonly<data1>
let p1:data2 = {
    id: 's1',
    students: [1, 2]
}    
console.log(p1)
p1.id = 's3'

6.3 Pick从 Type 中选择一组属性来构造新类型

interface data1{
    id:string,
    students:number[]
    title: string
}
type data2 = Pick<data1, 'id'|'students'>
let p1:data2 = {
    id: 's1',
    title: 'aaa', // title不在data2中
    students: [1, 2]
}    
console.log(p1)

6.4 Record 构造一个对象类型,属性键为 Keys,属性类型为 Type

用于创建具有特定键和值类型的对象映射

interface AppConfig {
  port: number;
  env: 'development' | 'production';
}

const config: Record<string, AppConfig> = {
  server: { port: 3000, env: 'development' },
  client: { port: 8080, env: 'production' },
};
type Scores = Record<'Math' | 'English' | 'Science', number>;  
  
const studentScores: Scores = {  
    Math: 90,  
    English: 85,  
    Science: 92  
};
enum Color {
  Red,
  Green,
  Blue,
}

const colorNameMap: Record<Color, string> = {
  [Color.Red]: 'Red',
  [Color.Green]: 'Green',
  [Color.Blue]: 'Blue',
};

最后

至此,本次的技术探索之旅暂告一段落,但技术的海洋浩瀚无垠,我们的征程远未结束。

如果你觉得这篇博客为你带来了新的视角、解决了你的困惑或者激发了你的思考,那么请不要吝啬你的点赞收藏,让我们一起在技术的道路上携手前行,共同成长。

关注我的技术博客,未来还有更多精彩的技术分享和深度的探讨等待着大家。

每一次的点赞都是对我的鼓励

每一次的收藏都是知识的沉淀

让我们一起用技术的力量创造更美好的未来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值