前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是TS类型保护、泛型

什么是TS类型保护、泛型

原创
作者头像
炑焽
发布2024-08-11 09:53:06
680
发布2024-08-11 09:53:06

一、ts类型保护

1、内置类型保护

  • typeof 类型保护

使用 typeof 运算符来检查值的类型。

代码语言:ts
复制
function isString(x: any): x is string {
    return typeof x === "string";
}
  • instanceof 类型保护

使用 instanceof 运算符来检查值是否是某个类的实例。在这个例子中,x is Dog 是一个类型保护,它告诉TypeScript编译器,如果 isDog 函数返回 true,那么 x 一定是 Dog 类型。

代码语言:ts
复制
class Animal {
    eat(): void {
        console.log('Animal eats');
    }
}
class Dog extends Animal {
    bark(): void {
        console.log('Dog barks');
    }
}
function isDog(x: Animal): x is Dog {
    return x instanceof Dog;
}
let pet: Animal = new Dog();
if (isDog(pet)) {
    pet.bark();
} else {
    pet.eat();
}

2、自定义类型保护

当内置的类型保护不足以满足需求时,可以创建自定义的类型保护。这通常是通过编写一个返回类型保护签名的函数来实现的

代码语言:ts
复制
type Fish = { swim: () => void; };
type Bird = { fly: () => void; };
function isFish(x: Fish | Bird): x is Fish {
    return (x as Fish).swim !== undefined;
}
function handleAnimal(animal: Fish | Bird) {
    if (isFish(animal)) {
        animal.swim(); // 这里TypeScript知道animal是Fish类型
    } else {
        (animal as Bird).fly(); // 这里我们需要手动断言,因为TypeScript不知道else分支中animal是Bird类型
    }
}

二、泛型

泛型(Generics)允许定义灵活的组件,这些组件可以工作于多种数据类型。通过使用泛型,可以创建可重用的组件,这些组件可以适应多种数据类型,而无需为每种数据类型都重新编写代码。

1、定义泛型

泛型是通过在类型或函数名后面添加尖括号(< >)和类型参数来定义的。这些类型参数通常是大写字母(如T、U、V等),但它们可以是任何有效的标识符。

代码语言:ts
复制
type A<T, U> = T | U;
type Arr<T>=T[]
function fn<T>(arg: T): T {
    return arg;
}
function Fn<T>(n:T){
    return n;
}
let a: A<string,number> = 'hello world'
let arr:Arr<number>=[1,2,3]
let output = fn<string>("xiaomu");
let output2 = fn(20);
let output3 = Fn('hello world'); // 这里不需要 <string>,因为 TypeScript 会自动推断,也是常用写法
let output4=Fn<string>('hello world')
  • 泛型接口
代码语言:ts
复制
interface Fn<T> {
    (arg: T): T;
}
let identityFn: Fn<number> = (x) => x;
let result = identityFn(20); // result 的类型是 number,值为 20
console.log(result); // 输出 20
  • 泛型类
代码语言:ts
复制
class Foo<T> {
    username!:T;
}
class Tfo extends FOO<string>{}
let f=new Foo<string>();
let tf=new Tfo()
f.username='xiaomu'
tf.username='extends'
  • 多参数泛型类的使用
代码语言:ts
复制
class Fn<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
    constructor(zeroValue: T, add: (x: T, y: T) => T) {
        this.zeroValue = zeroValue;
        this.add = add;
    }
    zero(): T {
        return this.zeroValue;
    }
    addNumbers(x: T, y: T): T {
        return this.add(x, y);
    }
}
let myFn= new Fn<number>(0, (x, y) => x + y);
// 使用 zero 方法获取零值
let zero = myFn.zero();
console.log(zero); // 输出:0
// 使用 addNumbers 方法执行加法
let sum = myFn.addNumbers(5, 3);
console.log(sum); // 输出:8

2、泛型常见操作

  • 类型参数

在泛型定义中,类型参数(如T)用于表示类型占位符,这些占位符将在使用泛型时由具体的类型来替换。

  • 类型推断

在调用泛型函数或实例化泛型类时,TypeScript编译器会尝试根据提供的参数来推断类型参数。如果编译器无法推断出类型参数,可能需要显式地指定它们。

  • 泛型约束

可以使用extends关键字为泛型类型参数添加约束。这允许指定类型参数必须满足的接口或类型。

代码语言:ts
复制
interface Fn {
    length: number;
}
function Foo<T extends Fn>(arg: T): T {
    console.log(arg.length);  // 现在我们可以访问arg.length属性了
    return arg;
}
  • 泛型类型别名

可以使用type关键字为泛型创建类型别名

代码语言:ts
复制
type Fn<T> = { value: T };
let f: Fn<string> = { value: "Hello, world!" };
  • 默认泛型类型

在TypeScript 2.3及更高版本中,可以为泛型类型参数提供默认类型

代码语言:ts
复制
//接受两个参数:length(表示数组的长度)和 value(表示数组中每个元素的值)
function Arr<T = string>(length: number, value: T = "default"): Array<T> {
    let result: T[] = new Array(length);
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}
let a = Arr(3); // a 的类型是 string[]
let b = Arr<number>(3, 18); // b 的类型是 number[]
console.log(a); // 输出: ["default", "default", "default"]
console.log(b); // 输出: [42, 42, 42]
  • 泛型数组

泛型可以与数组一起使用,以创建可以包含任何数据类型的数组。

代码语言:ts
复制
let list: Array<number> = [1, 2, 3];
let list2: number[] = [1, 2, 3];
  • 泛型元组

ypeScript 3.0引入了泛型元组类型,允许你创建具有特定数量和类型的元素的元组。

代码语言:ts
复制
type Pair<T, U> = [T, U];
let pair: Pair<string, number> = ["hello world", 20];
  • 泛型映射类型

使用泛型映射类型,你可以基于一个已知的类型创建新的类型。

代码语言:ts
复制
type Fn<T> = {
    [P in keyof T]?: T[P];
};
type  Foo= {
    name: string;
    sex: string;
    age: number;
};

type f = Fn<Foo>; // { name?: string;  sex?: string;age?: number; }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、ts类型保护
    • 1、内置类型保护
      • 2、自定义类型保护
      • 二、泛型
        • 1、定义泛型
          • 2、泛型常见操作
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档