高级特性
这一节是 Typescript 的高级特性
1. 关键字
1.1 typeof
typeof
关键字可以用来获取变量的类型。
let a = 1;
type A = typeof a; // number
1.2 keyof
keyof
关键字可以用来获取对象的所有键。
type Person = {
name: string;
age: number;
};
type PersonKeys = keyof Person; // "name" | "age"
1.3 in
in
可以用来遍历对象的所有键, 下面的 Person1 和 Person2 是等价的.
type Keys = "name" | "age";
type Person1 = { [key in Keys]: string };
type Person2 = { name: string; age: string };
1.4 extends
extends
关键字可以用来限制泛型的类型范围。
type Person = {
name: string;
age: number;
};
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let person: Person = {
name: "John",
age: 25,
};
let name = getProperty(person, "name");
let age = getProperty(person, "age");
1.5 is
is
关键字可以用来定义类型保护函数。
function isString(value: unknown): value is string {
return typeof value === "string";
}
function isNumber(value: unknown): value is number {
return typeof value === "number";
}
function isBoolean(value: unknown): value is boolean {
return typeof value === "boolean";
}
function isObject(value: unknown): value is object {
return typeof value === "object" && value !== null;
}
function isArray(value: unknown): value is Array<any> {
return Array.isArray(value);
}
1.6 as
as
关键字可以用来进行类型断言。
let a: unknown = 1;
let b: number = a as number;
1.7 const
const
关键字在 Typescript 中除了和 Javascript 中一样用来声明常量之外, 还有其他用途。
const enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
// 编译后color的值为纯字符串"red"
const color = Color.Red;
const colors = ["red", "green", "blue"] as const;
// Color 的实际类型为 "red"|"green"|"blue"
type Color = (typeof colors)[number];
1.8 readonly
readonly
关键字可以用来声明只读属性。
type Person = {
readonly name: string;
readonly age: number;
};
let person: Person = {
name: "John",
age: 25,
};
person.name = "Tom"; // Error: Cannot assign to 'name' because it is a read-only property.
1.9 public 和 private
public
关键字用来声明公共属性。private
关键字用来声明私有属性。
class Person {
// name可以在类的内部和外部访问
public name: string;
// age只能在类的内部访问
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
const p = new Person("何方", 25);
console.log(p.name); // 何方
console.log(p.age); // Error: Property 'age' is private and only accessible within class 'Person'.
2. 泛型
介绍如何使用泛型(Generic)来增加代码的灵活性和重用性,以及如何创建泛型函数和泛型类。
function printArray<T>(array: T[]): void {
for (let item of array) {
console.log(item);
}
}
printArray<number>([1, 2, 3, 4, 5]);
printArray<string>(["apple", "banana", "orange"]);
type Person = {
name: string;
age: number;
};
function printPerson<P extends Person>(person: P) {
console.log(person);
}
function getValueFromKey<O, K extends keyof O>(obj: O, key: K): O[K] {
return obj[key];
}
const p: Person = { name: "何方", age: 1 };
console.log(getValueFromKey(p, "age"));
console.log(getValueFromKey(p, "name"));
3. 高级类型
介绍 TypeScript 中的高级类型,如交叉类型、联合类型、类型保护。
3.1 交叉类型
交叉类型(Intersection Types)表示同时是多个类型的类型。
type Animal = { name: string };
type Bird = { fly: () => void };
type Fish = { swim: () => void };
type BirdAndFish = Bird & Fish;
let birdAndFish: BirdAndFish = { fly: () => {}, swim: () => {} };
3.2 联合类型
联合类型(Union Types)表示是多个类型之一的类型。
type Status = "pending" | "inProgress" | "completed";
function getStatusMessage(status: Status): string {
if (status === "pending") {
return "Task is pending";
} else if (status === "inProgress") {
return "Task is in progress";
} else {
return "Task is completed";
}
}
3.3 类型保护
类型保护(Type Guards)用于在运行时判断一个变量的类型,以便在不同的情况下使用不同的类型。
function isString(value: unknown): value is string {
return typeof value === "string";
}
let p: unknown = 1;
if (typeof p === "number") {
console.log(p.toFixed(2));
}
4. 函数重载
写过 Java、C 的人应该都知道函数重载(Function Overloads)这个概念。由于 Javascript 中的函数没有重载的概念,所以在 Typescript 中也没有函数重载的概念。但是 Typescript 提供了一种类似的机制,可以让我们在定义函数时,为同一个函数提供多个函数类型定义。
这个特性在工作中使用的不多,一般可以使用泛型和联合类型来替代。
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: any, b: any): any {
return a + b;
}
5. 常用内置范型
下面这些内置的泛型类型在实际开发中非常有用,你可以在 TypeScript 官方文档中找到它们的详细定义。
5.1 Partial
用于把一个对象的字段全部变为可选项。
type Partial<T> = {
[P in keyof T]?: T[P];
};
interface Person {
name: string;
age: number;
}
// name 和 age 属性全部变成了可选的
let john: Partial<Person> = {};
5.2 Required
用于把一个对象的字段全部变为必选项。
type Required<T> = {
[P in keyof T]-?: T[P];
};
interface Person {
name?: string;
age?: number;
}
// name 和 age 属性全部变成了必选的
let john: Required<Person> = { name: "John", age: 25 };
5.3 Readonly
用于把一个对象的字段全部变为只读。
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
interface Person {
name: string;
age: number;
}
// name 和 age 属性全部变成了只读的
let john: Readonly<Person> = { name: "John", age: 25 };
john.name = "xx"; // error
5.4 Record
用于声明一个纯对象,其属性名的类型由泛型参数决定,属性值的类型由另一个泛型参数决定。
type Record<K extends keyof any, T> = {
[P in K]: T;
};
// 创建一个对象,其属性名的类型为string,属性值的类型为number
let scores: Record<string, number> = {
John: 100,
Bob: 90,
Alice: 80,
};
5.5 Pick
用于从一个对象中挑选出指定的属性。
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface Person {
name: string;
age: number;
}
type PersonName = Pick<Person, "name">;
5.6 Omit
用于从一个对象中剔除指定的属性。
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
interface Person {
name: string;
age: number;
}
type PersonWithoutAge = Omit<Person, "age">;
5.7 Exclude
用于从一个类型中剔除指定的子类型。
type Exclude<T, U> = T extends U ? never : T;
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
5.8 Extract
用于从一个类型中提取指定的子类型。
type Extract<T, U> = T extends U ? T : never;
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void
5.9 NonNullable
用于从一个类型中剔除 null
和 undefined
。
type NonNullable<T> = T extends null | undefined ? never : T;
type T0 = NonNullable<string | number | undefined>; // string | number
5.10 Parameters
用于获取函数类型的参数类型组成的元组类型。
type Parameters<T extends (...args: any) => any> = T extends (
...args: infer P
) => any
? P
: never;
type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [string]
5.11 ReturnType
用于获取函数类型的返回值类型。
type ReturnType<T extends (...args: any) => any> = T extends (
...args: any
) => infer R
? R
: any;
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
6. 声明文件
介绍如何为第三方 JavaScript 库编写类型声明文件,以提供类型检查和代码提示的支持。
// math.d.ts
declare function add(a: number, b: number): number;
declare function subtract(a: number, b: number): number;
// app.ts
import { add, subtract } from "./math";
let result = add(10, 5);
console.log(result);
希望以上示例代码和对你有帮助!如果需要进一步了解每个章节的详细内容,你可以点击对应的,它们将带你进入 TypeScript 官方文档的相关部分。