JavaScript与TypeScript区别
JavaScript和TypeScript是两种不同的编程语言,本质上可以看作是JavaScript的超集。
- 类型系统:JavaScript是一种动态类型语言,变量的类型在运行时确定。而TypeScript是一种静态类型语言,变量的类型在编译时确定,并且可以通过类型检查器进行类型检查。
- 类型注解:在TypeScript中,可以为变量、函数参数、函数返回值等显式指定类型注解。这使得代码更易于理解、维护和调试。
- 类与接口:TypeScript支持类和接口的概念,使得面向对象编程更加便捷和强大。在JavaScript中,可以通过原型继承来实现类似的功能,但相对来说更为繁琐。
- 编译过程:TypeScript代码需要通过编译器进行编译,生成JavaScript代码,而JavaScript代码可以直接在浏览器或Node.js环境中运行。
- 生态系统: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 numbers: number[] = [1, 2, 3, 4, 5];
let fruits: string[] = ["apple", "banana", "orange"];
元组类型
元组用于表示已知元素数量和类型的数组,每个元素的类型可以不同,但需要按照定义的类型顺序放置。
let person: [string, number] = ["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 result: number = add(5, 3); // result将会是8
-
add函数接受两个参数x和y,它们都必须是数字类型(: number)。 - 函数返回类型被指定为
number,这意味着该函数返回一个数字。
函数表达式
let multiply = function (x: number, y: number): number {
return x * y;
};
let product: number = multiply(4, 5); // 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(1, 2, 3)); // 输出: 6
console.log(sum(4, 5, 6, 7)); // 输出: 22
-
...numbers是一个剩余参数,它可以接受任意数量的数字参数,并将它们存储在一个数组中。 -
reduce函数用于计算数组中所有数字的总和。
函数类型
type MathOperation = (x: number, y: number) => number;
let addition: MathOperation = (a, b) => a + b;
let subtraction: MathOperation = (a, b) => a - b;
console.log(addition(3, 4)); // 输出: 7
console.log(subtraction(8, 5)); // 输出: 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 myIdentity: GenericIdentityFn = 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 {
length: number;
}
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 中的一个重要特性,提供了一种编写通用和灵活代码的方式。示例中展示了四种用法:
- 泛型函数:通过
<T>定义泛型类型变量,并将其作为参数和返回值的类型。可以处理不同类型的参数并返回相同类型的结果。 - 泛型接口:通过泛型接口描述具有泛型函数签名的函数类型,增强代码的可读性和灵活性。
- 泛型类:允许创建适用于不同类型的实例的类,可以在属性和方法中使用泛型类型参数,提高代码的通用性和复用性。
- 泛型约束:通过
extends关键字约束泛型类型参数,要求其满足特定接口或条件。可以在泛型函数中使用,提高代码的类型安全性。
通过泛型,我们可以编写更具通用性、灵活性和可维护性的代码,更好地满足不同场景的需求。