likes
comments
collection
share

TypeScript类型注解123

作者站长头像
站长
· 阅读数 9

TypeScript是JavaScript的一个超集,它为这门语言添加了静态类型检查能力。类型注解是TypeScript的核心特性之一,允许开发者指定变量、函数参数和返回值的类型。这样做可以提高代码的清晰度和可维护性,并在编译期间捕捉潜在的错误。下面我将深入解释TypeScript中的类型注解和高级类型功能。

基础类型注解

在TypeScript中,可以为变量、函数参数和返回值指定类型,以确保它们按预期方式工作。

变量类型注解

变量类型注解简单明了,它们指明了变量可以存储的数据类型。

let isActive: boolean = true; // 只能赋值为true或false
let total: number = 0; // 任何数字,包括整数和浮点数
let name: string = "John Doe"; // 任何字符串

数组类型注解

数组类型注解指定了数组中元素的类型,确保数组中的所有元素都是同一类型。

let numbers: number[] = [1, 2, 3, 4, 5]; // 数组中的每个元素都必须是数字
let words: Array<string> = ["hello", "world"]; // 使用泛型语法定义字符串数组
let items: Array<string | number> = ["hello", "world", 1, 2]; // 这里,Array<string | number> 是使用泛型 Array<T> 语法,并将 string | number 作为泛型参数传递,表示数组中的元素可以是字符串或数字。

函数类型注解

函数类型注解指定了参数类型和函数返回值的类型。

// 指定函数参数和返回值的类型
function greet(name: string): string {
    return "Hello, " + name;
}

对象类型注解

对象类型注解可以通过接口(interface)或类型别名(type)来定义。

// 使用接口定义对象类型
interface User {
    name: string;
    age: number;
}

let user: User = {
    name: "Jane Doe",
    age: 30
};

高级类型功能

TypeScript提供了多种高级类型功能,允许开发者创建更复杂和可重用的类型定义。

泛型(Generics)

泛型是类型参数化的工具,它允许你定义一个函数、接口或类的类型,使其可以在多种类型之间工作而不失类型信息。

// 定义一个泛型函数
function identity<T>(arg: T): T {
    return arg;
}

// 使用时可以指定T为任意类型
let output = identity<string>("myString");

泛型提高了函数或类的灵活性,同时保持了类型安全。

交叉类型(Intersection Types)

交叉类型是将多个类型合并为一个类型,这通常用于组合多个类型的特性。

// 将两个类型合并成一个
type ReadableStreamable = Readable & Streamable;

在上面的示例中,ReadableStreamable 将具有 ReadableStreamable 两个类型的所有属性。

联合类型(Union Types)

联合类型表示一个值可以是几个不同类型中的任意一个。

// 参数可以是字符串或数字
function padLeft(value: string, padding: string | number) {
    // ...
}

在这个例子中,padding 可以是字符串或数字。

类型别名(Type Aliases)

类型别名用于给复杂的类型表达式创建一个新名字。

// 创建一个联合类型别名
type StringOrError = string | Error;

StringOrError 可以是字符串或错误对象。

映射类型(Mapped Types)

映射类型可以通过旧类型的每个属性来创建新类型。

// 创建一个只读版本的类型
type ReadOnly<T> = { readonly [P in keyof T]: T[P] };

在这里,ReadOnly<T> 创建了一个 T 的只读版本。

条件类型(Conditional Types)

条件类型根据类型关系在两种类型之间选择。

// 根据条件选择类型
type Check<T> = T extends string ? boolean : number;

如果 T 可以赋值给 string,那么 Check<T> 就是 boolean 类型;否则是 number 类型。

类型断言

类型断言允许开发者指定一个值的具体类型。

// 使用类型断言
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

枚举(Enums)

枚举是一种特殊的类型,它定义了一组命名的常数。

// 定义一个数字枚举
enum Direction {
    Up = 1,
    Down,
    Left,
    Right,
}

元组(Tuples)

元组允许你表达一个已知元素数量和类型的数组。

// 定义一个元组类型
let x: [string, number];
x = ["hello", 10]; // 正确

Never类型

never 类型表示那些永不存在的值的类型。

// never类型的函数
function error(message: string): never {
    throw new Error(message);
}

类型守卫

类型守卫用于缩小类型的范围。

// 类型守卫的示例
function isFish(pet: Fish | Bird): pet is Fish {
    return (pet as Fish).swim !== undefined;
}

类型推断

当没有明确指出类型时,TypeScript会根据上下文自动推断出一个类型。

// 类型推断的示例
let x = 3; // 类型被推断为number

类型兼容性

TypeScript中的类型兼容性是基于结构子类型的。

interface Named {
    name: string;
}

class Person {
    name: string;
}

let p: Named;
p = new Person(); // 结构类型兼容性

声明合并

TypeScript允许同一个名字的接口或命名空间的多个声明合并为一个声明。

// 接口声明合并
interface Box {
    height: number;
}

interface Box {
    width: number;
}

let box: Box = { height: 5, width: 6 }; // 合并后的接口

typeinterface 的区别

扩展性

interface 是开放式的,可以通过声明合并来扩展,而 type 是封闭的,不支持声明合并。

// `interface` 可以扩展
interface Animal {
    name: string;
}

interface Bear extends Animal {
    honey: boolean;
}

// `type` 不能合并,但可以通过交叉类型来扩展
type Animal = {
    name: string;
};

type Bear = Animal & { 
    honey: boolean 
};

推荐使用场景

  • 当定义对象的形状,尤其是希望在多个地方被扩展或实现时,使用 interface
  • 当定义联合类型、交叉类型,或者需要利用类型操作时,使用 type

通过上述解释,我们可以看到TypeScript提供了强大的类型系统,它不仅包括JavaScript的基本类型,还增加了枚举、元组、泛型等高级类型,以及类型守卫、类型兼容性等高级特性。这些工具可以帮助开发者编写更加健壮和易于维护的代码。

转载自:https://juejin.cn/post/7358704845735788555
评论
请登录