跳到主要内容

高级特性

- · -

这一节是 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

用于从一个类型中剔除 nullundefined

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 官方文档的相关部分。


参考文档

  1. 泛型
  2. 接口与类型别名
  3. 类型推断与型别兼容性
  4. 高级类型
  5. 声明文件
该内容为何方原创,转载请注明本页地址
https://iamhefang.cn/tutorials/typescript/高级特性