学习笔记
学习笔记
类型推断
在 TypeScript 中,类型推断是编译器根据代码上下文自动推断变量的类型。这意味着你不需要显式地为每个变量指定类型,编译器会根据赋值的类型推断出适当的类型。例如:
let x = 10; // x 的类型推断为 number
let y = "Hello"; // y 的类型推断为 string
let z = [1, 2, 3]; // z 的类型推断为 number[]
如果你想要显式地指定类型,可以这样做:
let x: number = 10;
let y: string = "Hello";
let z: number[] = [1, 2, 3];
这样可以增强代码的可读性和类型安全性。
提示
x赋值为一个字符串将报错
TypeScript 在类型推断时会根据变量第一次赋值的类型来确定变量的类型,并在后续赋值时保持该类型。如果你尝试将一个变量赋值为不同类型的值,TypeScript 会报错。
例如:
codelet x = 10; // x 的类型被推断为 number
x = "Hello"; // 这里会报错,因为 x 已经被推断为 number 类型,不能赋值为 string 类型
如果你想要让 x 可以是多种类型,可以使用联合类型:
codelet x: number | string = 10;
x = "Hello"; // 这样是允许的
这样定义的 x 可以是 number 或 string 类型的值。
类型断言
类型断言是在 TypeScript 中的一种特性,它允许你告诉编译器某个值的具体类型。它有两种语法形式:尖括号语法和as语法。
- 尖括号语法:
codelet someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
- as 语法:
codelet someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
这两种形式是等价的,你可以选择其中一种来使用。类型断言告诉编译器“我知道这个值的类型是什么”,这样编译器就不会给出类型错误。
注意
使用类型断言时要确保你确实了解变量的类型,否则可能会导致运行时错误(编译时不报错)。
数组 元组 枚举
在 TypeScript 中,数组、元组和枚举是常用的数据类型,它们可以帮助你更有效地组织和操作数据。
数组(Array)
数组是一组按顺序排列的同类型元素的集合。你可以通过以下方式声明和初始化数组:
codelet numbers: number[] = [1, 2, 3, 4, 5]; // 数组类型为 number
let fruits: string[] = ["apple", "banana", "orange"]; // 数组类型为 string
元组(Tuple)
元组是一种特殊的数组类型,它允许你指定数组中每个位置的元素类型。
code
let person: [string, number] = ["John", 25]; // 第一个元素是 string 类型,第二个元素是 number 类型
可选值
在 TypeScript 中,你可以使用元组中的可选值来定义元组中的一部分元素为可选的。这样做可以使元组中的某些值可以为 undefined
或其他指定类型的值。
例如:
let person: [string, number, boolean?] = ["John", 25]; // 最后一个元素是可选的,可以省略
在这个例子中,元组 person
包含了一个字符串和一个数字,并且最后一个元素是可选的布尔值。这意味着你可以选择性地在初始化元组时提供或省略最后一个值:
let person1: [string, number, boolean] = ["John", 25, true]; // 完整的初始化
let person2: [string, number] = ["John", 25]; // 最后一个元素被省略
这种方式允许你在不强制提供所有元组元素的情况下初始化元组,并且可以根据需要添加或删除可选值
枚举(Enum)
枚举是一种数据类型,用于定义数值集合并给数值取名。
enum Color {
Red,
Green,
Blue,
}
let color: Color = Color.Red; // color 的值为 0,即 Color.Red
枚举可以指定初始值,也可以指定字符串值或计算值。
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
let color: Color = Color.Red; // color 的值为 1,即 Color.Red
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
let color: Color = Color.Red; // color 的值为 "RED",即 Color.Red
函数
在 TypeScript 中,你可以使用函数来组织代码并执行特定的任务。函数可以接受参数并返回一个值,也可以不返回任何值(void)。
以下是一个简单的 TypeScript 函数示例:
function add(a: number, b: number): number {
return a + b;
}
let result = add(3, 5); // 调用 add 函数,并将结果赋值给 result
console.log(result); // 输出:8
在这个例子中,函数 add
接受两个参数(都是数字类型)并返回它们的和(也是一个数字类型)。在调用函数时,你需要提供函数期望的参数类型,并且函数的返回类型也可以指定。
你还可以使用可选参数、默认参数和剩余参数来增强函数的灵活性。例如:
function greet(name: string, greeting: string = "Hello"): void {
console.log(`${greeting}, ${name}!`);
}
greet("John"); // 输出:Hello, John!
greet("Sarah", "Hi"); // 输出:Hi, Sarah!
这里的 greeting
参数是一个默认参数,如果你不提供它,它将默认为 "Hello"。void
表示这个函数没有返回值。
除了普通的命名函数之外,你还可以使用箭头函数(Arrow Functions)来定义函数。箭头函数通常更简洁,并且具有更清晰的词法作用域。例如:
let multiply = (a: number, b: number): number => {
return a * b;
};
console.log(multiply(2, 4)); // 输出:8
可选参数和默认值
在 TypeScript 中,你可以使用可选参数和默认参数来增强函数的灵活性。
可选参数
在函数参数后面加上问号 ?
表示该参数是可选的,调用函数时可以选择性地提供该参数。例如:
function greet(name: string, greeting?: string): void {
if (greeting) {
console.log(`${greeting}, ${name}!`);
} else {
console.log(`Hello, ${name}!`);
}
}
greet("John"); // 输出:Hello, John!
greet("Sarah", "Hi"); // 输出:Hi, Sarah!
在这个例子中,greeting
参数是可选的,如果不提供,则默认为 "Hello"。
默认参数
在函数参数声明时直接给参数赋值表示该参数是默认参数。调用函数时,如果不提供对应参数的值,则使用默认值。例如:
function greet(name: string, greeting: string = "Hello"): void {
console.log(`${greeting}, ${name}!`);
}
greet("John"); // 输出:Hello, John!
greet("Sarah", "Hi"); // 输出:Hi, Sarah!
在这个例子中,greeting
参数被赋予了默认值 "Hello"。如果不提供该参数的值,则会使用默认值。
可变参数
在 TypeScript 中,你可以使用剩余参数(Rest Parameters)来处理可变数量的参数。剩余参数允许你将多个参数收集到一个变量中作为函数的最后一个参数。
以下是一个示例:
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 输出:15
console.log(sum(10, 20)); // 输出:30
在这个例子中,...numbers
是剩余参数语法,它会收集所有传递给函数的参数并将它们放入一个数组中。然后我们使用数组的 reduce
方法来计算这些数字的总和。
注意
注意,剩余参数必须是函数的最后一个参数,而且一个函数只能有一个剩余参数。
接口
在 TypeScript 中,接口(Interfaces)用于定义代码中的数据结构。接口定义了一个对象的形状,包括属性和方法,但不包含实现。
以下是一个简单的接口示例:
interface Person {
name: string;
age: number;
greet(): void;
}
let john: Person = {
name: "John",
age: 30,
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
};
john.greet(); // 输出:Hello, my name is John and I'm 30 years old.
在这个例子中,Person
接口定义了一个人的数据结构,包括 name
和 age
属性,以及一个 greet
方法。然后我们创建了一个符合该接口的对象 john
,并实现了 greet
方法。
接口可以用于提高代码的可读性和可维护性,以及进行类型检查和代码提示。你可以根据需要定义任意数量的接口,并在代码中使用它们来描述对象的形状。
类型别名
在 TypeScript 中,类型别名(Type Aliases)允许你为现有的类型创建一个新的名称。这样可以方便地重用复杂类型或为类型提供更具描述性的名称。
以下是一个简单的类型别名示例:
type ID = string | number;
function processID(id: ID): void {
console.log(`Processing ID: ${id}`);
}
processID("123"); // 输出:Processing ID: 123
processID(456); // 输出:Processing ID: 456
在这个例子中,type ID = string | number;
创建了一个类型别名 ID
,它表示可以是字符串或数字类型的值。然后我们可以使用 ID
类型作为函数参数类型,以及在其他地方重复使用。
类型别名的另一个常见用途是创建复杂类型的别名,例如联合类型、交叉类型或对象类型。这可以使代码更易于理解和维护。例如:
type Person = {
name: string;
age: number;
};
type Employee = Person & {
employeeID: number;
};
let employee: Employee = {
name: "John",
age: 30,
employeeID: 12345
};
在这个例子中,我们创建了两个类型别名 Person
和 Employee
,然后使用交叉类型将它们合并为一个新的复杂类型。
范型
范型(Generics)是 TypeScript 中的一种强大的工具,用于创建可重用的组件,能够在不同类型之间共享代码。范型允许你编写函数或类,可以在调用时指定具体的类型。
以下是一个简单的范型函数示例:
function identity<T>(arg: T): T {
return arg;
}
let result = identity<number>(10); // 指定类型为 number
console.log(result); // 输出:10
let value = identity<string>("Hello"); // 指定类型为 string
console.log(value); // 输出:Hello
在这个例子中,<T>
表示范型类型参数。在调用 identity
函数时,我们可以通过 identity<number>
或 identity<string>
来指定具体的类型,从而使函数返回相应类型的参数。
范型不仅适用于函数,还可以应用于类和接口。例如,你可以创建一个范型类来操作任意类型的数据,或者使用范型接口来定义范型对象的形状。
范型使得代码更加灵活和可重用,同时提高了类型安全性和可维护性。
提示
在 TypeScript 中,T
并不是一个特殊字符,它只是一个表示类型的占位符或标识符。在范型中,通常使用 T
表示类型参数,但实际上你可以使用任何合法的标识符来表示类型参数。
- 0
- 0
- 0
- 0
- 0
- 0