TypeScript(TS)简介、类型体操及常见使用场景

TypeScript(TS)简介、类型体操及常见使用场景

一、TypeScript 简介

TypeScript 是 JavaScript 的超集,它扩展了 JavaScript 的语法,为其添加了静态类型系统。这意味着在编写代码时,我们可以为变量、函数参数和返回值等指定类型,在编译阶段就能发现类型相关的错误,而不是像 JavaScript 那样在运行时才暴露错误,从而提高代码的稳定性和可维护性。

安装与使用

首先,确保你已经安装了 Node.js。然后,通过 npm 全局安装 TypeScript:

npm install -g typescript

安装完成后,就可以使用 tsc 命令将 TypeScript 文件(.ts)编译成 JavaScript 文件(.js)。

基本类型

TypeScript 支持多种基本类型,以下是一些常见的示例:

// 布尔类型
let isDone: boolean = false; 

// 数字类型
let myNumber: number = 42; 

// 字符串类型
let myString: string = "Hello, TypeScript!"; 

// 数组类型
let numbers: number[] = [1, 2, 3]; 
// 或者使用泛型语法
let anotherNumbers: Array<number> = [4, 5, 6]; 

// 元组类型,用于表示固定长度和类型的数组
let user: [string, number] = ["John", 30]; 

// null 和 undefined
let myNull: null = null; 
let myUndefined: undefined = undefined; 

// void 类型,通常用于表示函数没有返回值
function logMessage(message: string): void {
    console.log(message);
}

// any 类型,不推荐过度使用,它允许赋值为任意类型
let anyValue: any = "This could be any type"; 
anyValue = 123; 
  • 为变量指定类型(如 isDone: boolean),这样在赋值时,如果类型不匹配,TypeScript 编译器会报错,有助于发现潜在错误。
  • 数组类型 number[] 或 Array<number> 明确了数组元素的类型。
  • 元组类型 [string, number] 规定了数组元素的顺序和类型。
  • void 用于标识函数无返回值,确保函数定义和调用的一致性。
  • any 类型虽然灵活,但会失去 TypeScript 类型检查的优势,应谨慎使用。

二、TypeScript 类型体操

类型体操是指通过 TypeScript 的类型系统来实现复杂的类型转换和推导,通常涉及使用类型别名、泛型、条件类型、映射类型等高级类型特性。

类型别名

类型别名可以为一个类型定义一个新的名字,增加代码的可读性和可维护性。

typescript

// 定义一个类型别名表示坐标
type Coordinate = [number, number]; 

// 使用类型别名
let point: Coordinate = [10, 20]; 
  • type Coordinate = [number, number] 定义了一个名为 Coordinate 的类型别名,它代表一个包含两个 number 类型元素的元组。
  • let point: Coordinate = [10, 20]; 使用这个类型别名来声明变量 point,这样代码更易读,且如果需要修改坐标的类型结构,只需在类型别名定义处修改。

泛型

泛型允许我们在定义函数、接口或类时不指定具体的类型,而是在使用时再确定类型,增加了代码的复用性。

// 定义一个泛型函数,用于返回数组中的第一个元素
function getFirst<T>(array: T[]): T | undefined {
    return array.length > 0? array[0] : undefined;
}

// 使用泛型函数,T 会根据传入的数组类型自动推导为 string
let firstString = getFirst(["apple", "banana"]); 
// T 会自动推导为 number
let firstNumber = getFirst([1, 2, 3]); 
  • function getFirst<T>(array: T[]): T | undefined 定义了一个泛型函数 getFirst<T> 表示类型参数,T 可以代表任何类型。array: T[] 表示函数接受一个元素类型为 T 的数组,返回值类型要么是 T(如果数组有元素),要么是 undefined(如果数组为空)。
  • 当调用 getFirst(["apple", "banana"]) 时,TypeScript 会根据传入的数组类型自动推导 T 为 string,从而保证返回值类型的正确性。

条件类型

条件类型允许我们根据条件来选择不同的类型。

// 定义一个条件类型,如果 T 是 string 类型,则返回 'is string',否则返回 'not string'
type IsString<T> = T extends string? 'is string' : 'not string'; 

// 使用条件类型
type result1 = IsString<string>; // 'is string'
type result2 = IsString<number>; // 'not string'
  • type IsString<T> = T extends string? 'is string' : 'not string'; 定义了一个条件类型 IsString,它接受一个类型参数 TT extends string 是条件判断,如果 T 是 string 类型,则返回 'is string',否则返回 'not string'
  • type result1 = IsString<string>; 和 type result2 = IsString<number>; 分别使用这个条件类型,根据传入的类型参数得到不同的结果类型。

映射类型

映射类型允许我们基于一个已有的类型创建新的类型,通过对已有类型的属性进行变换。

// 定义一个原始类型
type User = {
    name: string;
    age: number;
    email: string;
};

// 使用映射类型将 User 类型的所有属性变为可选
type OptionalUser = {
    [P in keyof User]?: User[P];
};

// 使用映射类型将 User 类型的所有属性变为只读
type ReadonlyUser = {
    readonly [P in keyof User]: User[P];
};

// 创建 OptionalUser 类型的实例
let optionalUser: OptionalUser = {}; 
optionalUser.name = "Alice"; 

// 创建 ReadonlyUser 类型的实例
let readonlyUser: ReadonlyUser = {
    name: "Bob",
    age: 25,
    email: "bob@example.com"
};
// readonlyUser.name = "Charlie"; // 这会报错,因为属性是只读的
  • type User = {... } 定义了一个 User 类型。
  • type OptionalUser = {... } 使用映射类型 [P in keyof User]?: User[P];keyof User 获取 User 类型的所有属性名,P in keyof User 遍历这些属性名,? 使每个属性变为可选。
  • type ReadonlyUser = {... } 使用映射类型 readonly [P in keyof User]: User[P];readonly 关键字使每个属性变为只读。

三、常见使用场景

大型项目开发

在大型项目中,多人协作开发,代码规模大且结构复杂。TypeScript 的静态类型系统可以帮助开发者更好地理解代码结构,减少因类型错误导致的 bug。

// 定义一个用户接口
interface User {
    id: number;
    name: string;
    email: string;
}

// 定义一个函数,接受 User 类型的参数
function sendWelcomeEmail(user: User) {
    console.log(`Welcome, ${user.name}! Your email is ${user.email}`);
}

let newUser: User = {
    id: 1,
    name: "Eve",
    email: "eve@example.com"
};

sendWelcomeEmail(newUser); 
  • interface User {... } 定义了 User 接口,明确了用户对象应具备的属性和类型。
  • function sendWelcomeEmail(user: User) 函数接受 User 类型的参数,确保传入的对象符合 User 接口的定义,提高代码的健壮性。

库和框架开发

对于库和框架开发者,TypeScript 可以提供清晰的类型定义,方便其他开发者使用。例如,开发一个简单的数组操作库:

// 定义一个泛型函数,用于过滤数组
function filterArray<T>(array: T[], callback: (item: T) => boolean): T[] {
    let result: T[] = [];
    for (let item of array) {
        if (callback(item)) {
            result.push(item);
        }
    }
    return result;
}

// 使用过滤函数
let numbers = [1, 2, 3, 4, 5];
let evenNumbers = filterArray(numbers, (num) => num % 2 === 0); 
  • function filterArray<T>(array: T[], callback: (item: T) => boolean): T[] 定义了一个泛型函数 filterArray,可以对任何类型的数组进行过滤操作,通过类型参数 T 保证了函数的通用性和类型安全性。

与 React 框架结合使用

在 React 开发中,TypeScript 可以帮助管理组件的 props 和 state 类型:

import React from'react';

// 定义一个组件的 props 类型
interface ButtonProps {
    text: string;
    onClick: () => void;
}

// 定义一个按钮组件
const Button: React.FC<ButtonProps> = ({ text, onClick }) => {
    return (
        <button onClick={onClick}>
            {text}
        </button>
    );
};

// 使用按钮组件
const App: React.FC = () => {
    const handleClick = () => {
        console.log('Button clicked');
    };
    return (
        <div>
            <Button text="Click me" onClick={handleClick} />
        </div>
    );
};

export default App;
  • interface ButtonProps {... } 定义了按钮组件 Button 的 props 类型,明确了 text 和 onClick 的类型。
  • const Button: React.FC<ButtonProps> 使用这个 props 类型定义按钮组件,确保组件使用时 props 的类型正确,提高代码的可维护性和可读性。
© 版权声明
THE END
喜欢就支持一下吧
点赞22 分享
评论 抢沙发

    暂无评论内容