TypeScript-泛型 | 青训营

104 阅读6分钟

JavaScript与TypeScript区别

JavaScript和TypeScript是两种不同的编程语言,本质上可以看作是JavaScript的超集。 20230826231234.png

  1. 类型系统:JavaScript是一种动态类型语言,变量的类型在运行时确定。而TypeScript是一种静态类型语言,变量的类型在编译时确定,并且可以通过类型检查器进行类型检查。
  2. 类型注解:在TypeScript中,可以为变量、函数参数、函数返回值等显式指定类型注解。这使得代码更易于理解、维护和调试。
  3. 类与接口:TypeScript支持类和接口的概念,使得面向对象编程更加便捷和强大。在JavaScript中,可以通过原型继承来实现类似的功能,但相对来说更为繁琐。
  4. 编译过程:TypeScript代码需要通过编译器进行编译,生成JavaScript代码,而JavaScript代码可以直接在浏览器或Node.js环境中运行。
  5. 生态系统:JavaScript有着丰富的生态系统,拥有大量的开源库和框架。TypeScript可以直接使用JavaScript的库和框架,且TypeScript具有更好的与其他JavaScript工具和框架的集成能力。

总结:TypeScript在JavaScript的基础上增加了类型系统和更多的语言特性,提供了更好的开发工具支持和更强的代码可靠性。但相应地,TypeScript代码需要编译步骤并且开发者需要花费更多的时间学习和掌握。

TypeScript基础类型

TypeScript 和 JavaScript 没有整数类型。

any 任意类型

any 类型可以表示任何类型的值,它与 JavaScript 中的动态类型类似,但是在 TypeScript 中使用它会丧失类型检查的好处,应尽量避免使用。

let anyValue: any = 42;  
anyValue = "Hello";  
anyValue = true;

number 数字类型

number 类型用来表示双精度 64 位浮点值,可以表示整数和分数。

let decimal: number = 6;  
let fraction: number = 3.14;  
let hex: number = 0xf00d;  
let binary: number = 0b1010;

string 字符串类型

string 类型表示一个字符序列,可以使用单引号或双引号表示,也可以使用反引号定义多行文本和内嵌表达式。

let firstName: string = "John";  
let lastName: string = 'Doe';  
let fullName: string = `My name is ${firstName} ${lastName}.`;

boolean 布尔类型

boolean 类型表示布尔值,只有两个可能的值:true 和 false

let isDone: boolean = false;  
let isWorking: boolean = true;

数组类型

数组用于存储相同类型的多个值。

let numbersnumber[] = [1, 2, 3, 4, 5];  
let fruitsstring[] = ["apple""banana""orange"];

元组类型

元组用于表示已知元素数量和类型的数组,每个元素的类型可以不同,但需要按照定义的类型顺序放置。

 

    let person: [stringnumber] = ["Alice"30];

枚举类型

枚举用于定义命名的数值集合。

enum Color {
Red,
Green,
Blue  
}

void 类型

用于标识方法返回值的类型,表示该方法没有返回值

 function showMessage(): void {
 console.log("Hello, world!");  
 }

null 和 undefined 类型

null 和 undefined 用于表示缺失的值。

 let nullValue: null = null;  
 let undefinedValue: undefined = undefined;

never 类型

never 类型是所有类型的子类型,表示永远不会出现的值,常用于抛出异常或无法执行到终点的函数。

function throwError(message: string): never {
throw new Error(message);  
}

TypeScript 函数

基本函数

 function add(x: number, y: number): number {
 return x + y;  
 }  

 let resultnumber = add(53); // result将会是8  
  •  add 函数接受两个参数 x 和 y,它们都必须是数字类型(: number)。
  •  函数返回类型被指定为 number,这意味着该函数返回一个数字。

函数表达式

let multiply = function (x: number, y: number): number {
return x * y;  
};  

let productnumber = multiply(45); // product将会是20  
  •  multiply 是一个匿名函数,它接受两个数字参数并返回它们的乘积。
  •  函数表达式的类型注解告诉 TypeScript 这个函数接受两个数字参数并返回一个数字。

可选参数

function greet(name: string, greeting?: string): string { 

if (greeting) {
return `${greeting}${name}!`;
} 
else {
return `Hello, ${name}!`; 
}  
}  

console.log(greet("Alice")); // 输出: Hello, Alice!  
console.log(greet("Bob""Hi")); // 输出: Hi, Bob!  
  •  greeting 参数被标记为可选的,使用 ? 来表示。这意味着你可以调用 greet 函数只传入一个参数,或者传入两个参数。
  •  函数体内根据是否传入了 greeting 参数来决定返回不同的问候语。

默认参数

 function greetWithDefault(name: string, greeting: string = "Hello"): string {  
 return `${greeting}${name}!`;  
}  

console.log(greetWithDefault("Alice")); // 输出: Hello, Alice!  
console.log(greetWithDefault("Bob""Hi")); // 输出: Hi, Bob!  
  • greeting 参数有一个默认值 "Hello",这意味着如果你不传入这个参数,它将默认为 "Hello"
  •  当传入 greeting 参数时,它将覆盖默认值。

剩余参数

function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);  
}  

console.log(sum(123)); // 输出: 6  
console.log(sum(4567)); // 输出: 22  
  •  ...numbers 是一个剩余参数,它可以接受任意数量的数字参数,并将它们存储在一个数组中。
  •  reduce 函数用于计算数组中所有数字的总和。

函数类型

type MathOperation = (x: number, y: number) => number;  

let additionMathOperation = (a, b) => a + b;  
let subtractionMathOperation = (a, b) => a - b;  

console.log(addition(34)); // 输出: 7  
console.log(subtraction(85)); // 输出: 3  
  •  MathOperation 是一个函数类型,它指定了函数接受两个数字参数并返回一个数字。
  •  可以使用 MathOperation 类型来声明变量,然后将函数分配给这些变量。

函数重载

function formatInput(input: string)string;  
function formatInput(input: number)string;  

function formatInput(input: string | number)string {
if (typeof input === "string") {
return input.toUpperCase();  
} else if (typeof input === "number") {
return input.toFixed(2);
}  
}  

console.log(formatInput("hello")); // 输出: "HELLO"  
console.log(formatInput(3.14159)); // 输出: "3.14"  
  • formatInput 函数有两个重载,一个接受字符串参数,另一个接受数字参数。
  • 在实际调用中,TypeScript 根据参数类型选择正确的重载。

TypeScript-泛型

泛型函数

function identity<T>(arg: T): T {  
    return arg;  
}  
  
let output = identity<string>("myString"); // output的类型将是 'string'  
  • identity 函数使用 <T> 来定义一个泛型类型变量 T
  • 参数 arg 和返回值都被标注为类型 T
  • 调用 identity 函数时,需要明确传入并指定泛型类型。

泛型接口

interface GenericIdentityFn {  
    <T>(arg: T): T;  
}  
  
function identity<T>(arg: T): T {  
    return arg;  
}  
  
let myIdentityGenericIdentityFn = identity;  
  •  GenericIdentityFn 是一个泛型接口,它描述了一个具有调用签名的函数类型。
  •  identity 函数符合 GenericIdentityFn 接口的定义,因此可以将 identity 赋值给变量 myIdentity

泛型类

class GenericNumber<T> {  
    zeroValue: T;  
    add(x: T, y: T) => T;  
}  
  
let myGenericNumber = new GenericNumber<number>();  
  •  GenericNumber 类接受一个泛型类型参数 T
  •  zeroValue 属性和 add 方法都可以使用泛型类型参数 T
  •  创建一个 GenericNumber 的实例时,需要明确指定泛型类型。

泛型约束

interface Lengthwise {  
    lengthnumber;  
}  
  
function loggingIdentity<T extends Lengthwise>(arg: T): T {  
    console.log(arg.length); // 现在我们知道它有一个 .length 属性,所以没有错误  
    return arg;  
}  
  •  Lengthwise 接口描述了一个对象必须具有 length 属性。
  • loggingIdentity 函数接受一个泛型类型参数 T,并使用 extends 关键字来约束 T 必须符合 Lengthwise 接口的定义。
  • 现在在函数体内我们可以安全地访问 arg.length 属性,因为编译器已经验证了它的类型。

总结

泛型是 TypeScript 中的一个重要特性,提供了一种编写通用和灵活代码的方式。示例中展示了四种用法:

  1. 泛型函数:通过 <T> 定义泛型类型变量,并将其作为参数和返回值的类型。可以处理不同类型的参数并返回相同类型的结果。
  2. 泛型接口:通过泛型接口描述具有泛型函数签名的函数类型,增强代码的可读性和灵活性。
  3. 泛型类:允许创建适用于不同类型的实例的类,可以在属性和方法中使用泛型类型参数,提高代码的通用性和复用性。
  4. 泛型约束:通过 extends 关键字约束泛型类型参数,要求其满足特定接口或条件。可以在泛型函数中使用,提高代码的类型安全性。

通过泛型,我们可以编写更具通用性、灵活性和可维护性的代码,更好地满足不同场景的需求。