TypeScript 语法详解
1. 基础类型
1.1 基本类型
// 布尔值
let isDone: boolean = true;
// 数字(支持十进制、十六进制、二进制、八进制)
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
// 字符串
let color: string = "blue";
let fullName: string = `Bob Bobbington`;
let sentence: string = `Hello, my name is ${fullName}`;
// 数组(两种写法)
let list1: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];
// 元组 Tuple
let tuple: [string, number] = ["hello", 10];
// 访问元组元素
let str: string = tuple[0];
let num: number = tuple[1];
// 枚举
enum Color {
Red = 1, // 可以从1开始编号
Green, // 2
Blue = 4 // 可以手动赋值
}
let c: Color = Color.Green; // 2
// Any(任意类型)
let notSure: any = 4;
notSure = "maybe a string";
notSure = false;
// Void(无任何类型)
function warnUser(): void {
console.log("This is a warning");
}
// Null 和 Undefined
let u: undefined = undefined;
let n: null = null;
// Never(永不存在的值的类型)
function error(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
// Object(非原始类型)
declare function create(o: object | null): void;
create({ prop: 0 });
create(null);
// 类型断言(两种方式)
let someValue: any = "this is a string";
let strLength1: number = (<string>someValue).length;
let strLength2: number = (someValue as string).length;
1.2 字面量类型
// 字符串字面量类型
type Direction = "north" | "south" | "east" | "west";
let dir: Direction = "north"; // 只能赋这四个值
// 数字字面量类型
type Dice = 1 | 2 | 3 | 4 | 5 | 6;
let dice: Dice = 3;
// 布尔字面量类型
type Success = true;
let success: Success = true;
// 模板字面量类型
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiPath = `/api/${HttpMethod}`;
let path: ApiPath = "/api/GET";
// 结合使用
type EventName = "click" | "mouseover" | "keydown";
type EventHandler = (event: Event) => void;
2. 变量声明
// let 和 const
let variable: string = "can be reassigned";
const constant: string = "cannot be reassigned";
// 解构赋值
let input: [number, number] = [1, 2];
let [first, second] = input;
// 对象解构
let o = { a: "foo", b: 12, c: "bar" };
let { a, b } = o;
let { a: newName1, b: newName2 } = o; // 重命名
// 函数参数解构
function f({ a, b = 0 } = { a: "" }): void {
// ...
}
f({ a: "yes" });
// 展开运算符
let firstArray = [1, 2];
let secondArray = [3, 4];
let bothPlus = [0, ...firstArray, ...secondArray, 5];
// 对象展开
let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { ...defaults, food: "rich" };
3. 接口
3.1 对象接口
// 基本接口
interface Person {
name: string;
age: number;
readonly id: number; // 只读属性
nickname?: string; // 可选属性
}
// 使用接口
let person: Person = {
name: "Alice",
age: 30,
id: 12345
};
// 接口继承
interface Employee extends Person {
employeeId: number;
department: string;
}
// 混合类型接口
interface Counter {
(start: number): string; // 函数
interval: number; // 属性
reset(): void; // 方法
}
// 可索引接口
interface StringArray {
[index: number]: string;
}
let myArray: StringArray = ["Bob", "Fred"];
3.2 函数类型接口
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
return src.search(sub) > -1;
};
// 使用类型别名定义函数类型
type SearchFunction = (source: string, subString: string) => boolean;
3.3 类类型接口
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
3.4 接口扩展
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square: Square = {
color: "blue",
penWidth: 5.0,
sideLength: 10
};
4. 类
4.1 基本类
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet(): string {
return `Hello, ${this.greeting}`;
}
}
let greeter = new Greeter("world");
4.2 继承
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number = 0): void {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) {
super(name); // 必须调用父类构造函数
}
move(distanceInMeters = 5): void {
console.log("Slithering...");
super.move(distanceInMeters); // 调用父类方法
}
}
4.3 访问修饰符
class Person {
public name: string; // 公共,默认修饰符
private age: number; // 私有,只能在类内部访问
protected id: string; // 受保护,只能在类及其子类中访问
readonly country: string; // 只读
constructor(name: string, age: number, id: string) {
this.name = name;
this.age = age;
this.id = id;
this.country = "China";
}
public getAge(): number {
return this.age; // 可以访问私有属性
}
}
class Employee extends Person {
private department: string;
constructor(name: string, age: number, id: string, department: string) {
super(name, age, id);
this.department = department;
}
public getDetails(): string {
return `${this.name} (${this.id}) works in ${this.department}`;
// this.age 无法访问(私有)
// this.id 可以访问(受保护)
}
}
4.4 参数属性
class Animal {
constructor(private name: string, public age: number) {
// 自动创建并初始化属性
}
getName(): string {
return this.name; // 可以直接访问
}
}
// 等同于
class AnimalTraditional {
private name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
4.5 Getter/Setter
class Employee {
private _fullName: string = "";
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (newName && newName.length > 0) {
this._fullName = newName;
} else {
throw new Error("Invalid name");
}
}
}
let employee = new Employee();
employee.fullName = "Alice Smith"; // 调用 setter
console.log(employee.fullName); // 调用 getter
4.6 静态属性
class Grid {
static origin = { x: 0, y: 0 };
calculateDistanceFromOrigin(point: { x: number; y: number }) {
let xDist = point.x - Grid.origin.x; // 通过类名访问
let yDist = point.y - Grid.origin.y;
return Math.sqrt(xDist * xDist + yDist * yDist);
}
}
4.7 抽象类
abstract class Department {
constructor(public name: string) {}
abstract printMeeting(): void; // 抽象方法,必须在派生类中实现
printName(): void {
console.log(`Department name: ${this.name}`);
}
}
class AccountingDepartment extends Department {
constructor() {
super("Accounting");
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10am.");
}
}
// let dept = new Department(); // 错误:无法创建抽象类的实例
let dept: Department = new AccountingDepartment(); // 允许
5. 函数
5.1 函数类型
// 函数声明
function add(x: number, y: number): number {
return x + y;
}
// 函数表达式
let myAdd: (x: number, y: number) => number = function(x, y) {
return x + y;
};
// 箭头函数
let myAdd2 = (x: number, y: number): number => x + y;
// 可选参数
function buildName(firstName: string, lastName?: string): string {
return lastName ? `${firstName} ${lastName}` : firstName;
}
// 默认参数
function buildName2(firstName: string, lastName = "Smith"): string {
return `${firstName} ${lastName}`;
}
// 剩余参数
function buildName3(firstName: string, ...restOfName: string[]): string {
return firstName + " " + restOfName.join(" ");
}
5.2 函数重载
// 重载签名
function pickCard(x: { suit: string; card: number; }[]): number;
function pickCard(x: number): { suit: string; card: number; };
// 实现签名
function pickCard(x: any): any {
if (Array.isArray(x)) {
return x.length;
} else if (typeof x === "number") {
return { suit: "hearts", card: x % 13 };
}
}
let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }];
let pickedCard1 = pickCard(myDeck); // number
let pickedCard2 = pickCard(15); // {suit: string; card: number;}
5.3 this 参数
interface Card {
suit: string;
card: number;
}
interface Deck {
suits: string[];
cards: number[];
createCardPicker(this: Deck): () => Card;
}
let deck: Deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function(this: Deck) {
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {
suit: this.suits[pickedSuit], // 正确绑定 this
card: pickedCard % 13
};
};
}
};
6. 泛型
6.1 泛型函数
// 基本泛型
function identity<T>(arg: T): T {
return arg;
}
// 使用
let output1 = identity<string>("myString"); // 显式指定类型
let output2 = identity("myString"); // 类型推断
// 多个类型参数
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
let swapped = swap([7, "hello"]); // ["hello", 7]
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity({ length: 10, value: 3 }); // 正确
// loggingIdentity(3); // 错误:数字没有length属性
// 在泛型约束中使用类型参数
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
let x = { a: 1, b: 2, c: 3 };
getProperty(x, "a"); // 正确
// getProperty(x, "m"); // 错误:"m"不是x的属性
6.2 泛型接口
// 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zeroValue: T, add: (x: T, y: T) => T) {
this.zeroValue = zeroValue;
this.add = add;
}
}
let myGenericNumber = new GenericNumber<number>(0, (x, y) => x + y);
6.3 泛型默认类型
interface A<T = string> {
name: T;
}
const a: A = { name: "hello" }; // 使用默认类型 string
const b: A<number> = { name: 123 }; // 指定类型 number
7. 枚举
7.1 数字枚举
enum Direction {
Up = 1, // 从1开始编号
Down, // 2
Left, // 3
Right // 4
}
// 编译为:
// var Direction;
// (function (Direction) {
// Direction[Direction["Up"] = 1] = "Up";
// Direction[Direction["Down"] = 2] = "Down";
// Direction[Direction["Left"] = 3] = "Left";
// Direction[Direction["Right"] = 4] = "Right";
// })(Direction || (Direction = {}));
7.2 字符串枚举
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
7.3 异构枚举(混合字符串和数字)
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
7.4 常量枚举
const enum Direction {
Up,
Down,
Left,
Right
}
let directions = [
Direction.Up, // 编译时被替换为 0
Direction.Down, // 1
Direction.Left, // 2
Direction.Right // 3
];
7.5 外部枚举
declare enum Enum {
A = 1,
B,
C = 2
}
8. 高级类型
8.1 联合类型
type StringOrNumber = string | number;
function padLeft(value: string, padding: StringOrNumber): string {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
return padding + value;
}
8.2 交叉类型
interface Person {
name: string;
age: number;
}
interface Employee {
company: string;
salary: number;
}
type EmployeePerson = Person & Employee;
let employee: EmployeePerson = {
name: "Alice",
age: 30,
company: "Tech Corp",
salary: 50000
};
8.3 类型保护
// typeof 类型保护
function padLeft(value: string, padding: string | number): string {
if (typeof padding === "number") {
// 这里 padding 是 number 类型
return Array(padding + 1).join(" ") + value;
}
// 这里 padding 是 string 类型
return padding + value;
}
// instanceof 类型保护
class Bird {
fly() { console.log("flying"); }
layEggs() { console.log("laying eggs"); }
}
class Fish {
swim() { console.log("swimming"); }
layEggs() { console.log("laying eggs"); }
}
function getSmallPet(): Bird | Fish {
return Math.random() > 0.5 ? new Bird() : new Fish();
}
let pet = getSmallPet();
if (pet instanceof Bird) {
pet.fly(); // 正确:pet 是 Bird 类型
} else {
pet.swim(); // 正确:pet 是 Fish 类型
}
// 自定义类型保护
interface Bird {
fly(): void;
layEggs(): void;
}
interface Fish {
swim(): void;
layEggs(): void;
}
function isFish(pet: Bird | Fish): pet is Fish {
return (pet as Fish).swim !== undefined;
}
if (isFish(pet)) {
pet.swim(); // pet 是 Fish 类型
} else {
pet.fly(); // pet 是 Bird 类型
}
8.4 索引类型
// keyof 操作符
interface Person {
name: string;
age: number;
location: string;
}
type PersonKeys = keyof Person; // "name" | "age" | "location"
// 索引访问操作符 T[K]
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
let person: Person = { name: "Alice", age: 30, location: "NYC" };
let name: string = getProperty(person, "name"); // string
let age: number = getProperty(person, "age"); // number
// 映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
type PersonPartial = Partial<Person>;
type ReadonlyPerson = Readonly<Person>;
8.5 条件类型
// 基本条件类型
type TypeName<T> = T extends string ? "string"
: T extends number ? "number"
: T extends boolean ? "boolean"
: T extends undefined ? "undefined"
: T extends Function ? "function"
: "object";
type T0 = TypeName<string>; // "string"
type T1 = TypeName<"a">; // "string"
type T2 = TypeName<true>; // "boolean"
// 分布式条件类型
type Diff<T, U> = T extends U ? never : T;
type Filter<T, U> = T extends U ? T : never;
type T3 = Diff<"a" | "b" | "c", "a" | "d">; // "b" | "c"
type T4 = Filter<"a" | "b" | "c", "a" | "d">; // "a"
// 条件类型中的推断
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type T5 = ReturnType<() => string>; // string
type T6 = ReturnType<(x: number) => number[]>; // number[]
// 内置条件类型
type T7 = Exclude<"a" | "b" | "c", "a" | "d">; // "b" | "c"
type T8 = Extract<"a" | "b" | "c", "a" | "d">; // "a"
type T9 = NonNullable<string | number | undefined>; // string | number
type T10 = InstanceType<typeof Array>; // any[]
9. 模块
9.1 导出
// math.ts
// 导出声明
export const pi = 3.14;
export interface Circle {
radius: number;
}
export class Calculator {
static add(x: number, y: number): number {
return x + y;
}
}
// 导出语句
const version = "1.0";
export { version };
// 重命名导出
export { version as apiVersion };
// 默认导出(每个模块只能有一个)
export default class MathUtils {
static multiply(x: number, y: number): number {
return x * y;
}
}
9.2 导入
// app.ts
// 导入命名的导出
import { pi, Calculator, type Circle } from "./math";
// 导入整个模块
import * as math from "./math";
// 导入默认导出
import MathUtils from "./math";
// 重命名导入
import { version as apiVersion } from "./math";
// 重新导出
export { pi } from "./math";
export * from "./math";
10. 命名空间
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
const lettersRegexp = /^[A-Za-z]+$/;
const numberRegexp = /^[0-9]+$/;
export class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string): boolean {
return lettersRegexp.test(s);
}
}
export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string): boolean {
return s.length === 5 && numberRegexp.test(s);
}
}
}
// 使用命名空间
let validators: { [s: string]: Validation.StringValidator } = {};
validators["ZIP code"] = new Validation.ZipCodeValidator();
validators["Letters only"] = new Validation.LettersOnlyValidator();
// 多文件命名空间
// Validation.ts
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
}
// LettersOnlyValidator.ts
/// <reference path="Validation.ts" />
namespace Validation {
const lettersRegexp = /^[A-Za-z]+$/;
export class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
}
11. 装饰器
11.1 类装饰器
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
// 装饰器工厂
function color(value: string) {
return function (constructor: Function) {
// 添加元数据等
};
}
@color("red")
class Car {}
11.2 方法装饰器
function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}
11.3 访问器装饰器
function configurable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}
class Point {
private _x: number;
private _y: number;
constructor(x: number, y: number) {
this._x = x;
this._y = y;
}
@configurable(false)
get x() { return this._x; }
@configurable(false)
get y() { return this._y; }
}
11.4 属性装饰器
function format(formatString: string) {
return function (target: any, propertyKey: string) {
// 添加元数据等
};
}
class Greeter {
@format("Hello, %s")
greeting: string;
constructor(message: string) {
this.greeting = message;
}
}
11.5 参数装饰器
function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {
// 添加验证逻辑
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet(@required name: string) {
return "Hello " + name + ", " + this.greeting;
}
}
12. 声明文件
12.1 声明变量
declare var jQuery: (selector: string) => any;
12.2 声明函数
declare function setTimeout(handler: (...args: any[]) => void, timeout?: number, ...args: any[]): number;
12.3 声明类
declare class Animal {
name: string;
constructor(name: string);
sayHi(): string;
}
12.4 声明枚举
declare enum Directions {
Up,
Down,
Left,
Right
}
12.5 声明命名空间
declare namespace jQuery {
function ajax(url: string, settings?: any): void;
namespace fn {
function extend(object: any): void;
}
}
12.6 声明模块
declare module "url" {
export interface Url {
protocol?: string;
hostname?: string;
pathname?: string;
}
export function parse(urlStr: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): Url;
}
12.7 全局声明
declare global {
interface Array<T> {
myMethod(): void;
}
}
Array.prototype.myMethod = function() {
// ...
};
13. 配置
13.1 tsconfig.json
{
"compilerOptions": {
/* 基本选项 */
"target": "es5", // 目标 ECMAScript 版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ESNext'
"module": "commonjs", // 模块系统: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'esnext'
"lib": ["es6", "dom"], // 要包含的库文件
"allowJs": true, // 允许编译 JavaScript 文件
"checkJs": true, // 在 .js 文件中报告错误
"jsx": "react", // JSX 代码生成: 'preserve', 'react-native', 'react'
/* 严格类型检查选项 */
"strict": true, // 启用所有严格类型检查选项
"noImplicitAny": true, // 禁止隐式的 any 类型
"strictNullChecks": true, // 启用严格的 null 检查
"strictFunctionTypes": true, // 启用严格的函数类型检查
"strictBindCallApply": true, // 启用严格的 bind/call/apply 检查
"strictPropertyInitialization": true, // 启用严格的属性初始化检查
"noImplicitThis": true, // 禁止隐式的 this 类型
"alwaysStrict": true, // 以严格模式解析并为每个源文件生成 "use strict"
/* 附加检查 */
"noUnusedLocals": true, // 报告未使用的局部变量
"noUnusedParameters": true, // 报告未使用的参数
"noImplicitReturns": true, // 不是函数的所有返回路径都有返回值时报错
"noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误
/* 模块解析选项 */
"moduleResolution": "node", // 模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
"baseUrl": "./", // 基础目录
"paths": { // 模块名到基于 baseUrl 的路径映射
"@/*": ["src/*"]
},
"rootDirs": [ // 根文件夹列表,其组合内容表示运行时的项目结构
"src/views",
"generated/views"
],
"typeRoots": [ // 要包含的类型声明文件路径列表
"node_modules/@types"
],
"types": [ // 要包含的类型声明文件名列表
"node",
"jest"
],
/* Source Map 选项 */
"sourceMap": true, // 生成相应的 .map 文件
"inlineSourceMap": false, // 生成单个 source maps 文件
"inlineSources": false, // 将代码与 sourcemaps 生成到一个文件中
/* 其他选项 */
"experimentalDecorators": true, // 启用实验性的装饰器
"emitDecoratorMetadata": true, // 为装饰器提供元数据支持
"esModuleInterop": true, // 允许 default import from non-default modules
"allowSyntheticDefaultImports": true, // 允许从没有默认导出的模块进行默认导入
"resolveJsonModule": true, // 允许导入 .json 文件
"declaration": true, // 生成相应的 .d.ts 文件
"declarationMap": true, // 为每个 .d.ts 文件生成 sourcemap
"outDir": "./dist", // 输出目录
"removeComments": true, // 删除注释
"newLine": "lf", // 指定换行符
"noEmit": false // 不生成输出文件
},
"include": [ // 要编译的文件
"src/**/*"
],
"exclude": [ // 排除的文件
"node_modules",
"**/*.spec.ts"
],
"files": [ // 要编译的特定文件列表
"src/core.ts"
],
"references": [ // 项目引用
{ "path": "./common" }
]
}
14. 实用工具类型
// Partial<T> - 使所有属性变为可选
interface Todo {
title: string;
description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
return { ...todo, ...fieldsToUpdate };
}
// Required<T> - 使所有属性变为必需
interface Props {
a?: number;
b?: string;
}
const obj: Required<Props> = { a: 5, b: "hello" };
// Readonly<T> - 使所有属性变为只读
const todo: Readonly<Todo> = {
title: "Delete inactive users",
description: "..."
};
// todo.title = "Hello"; // 错误:只读
// Record<K, T> - 构造一个类型,其属性键为 K,属性值为 T
interface PageInfo {
title: string;
}
type Page = "home" | "about" | "contact";
const pages: Record<Page, PageInfo> = {
home: { title: "Home" },
about: { title: "About" },
contact: { title: "Contact" }
};
// Pick<T, K> - 从 T 中选择一组属性 K
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false
};
// Omit<T, K> - 从 T 中排除一组属性 K
type TodoInfo = Omit<Todo, "completed" | "description">;
const todoInfo: TodoInfo = {
title: "Pick up kids"
};
// Exclude<T, U> - 从 T 中排除可以赋值给 U 的类型
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
// Extract<T, U> - 从 T 中提取可以赋值给 U 的类型
type T1 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
// NonNullable<T> - 从 T 中排除 null 和 undefined
type T2 = NonNullable<string | number | undefined>; // string | number
// Parameters<T> - 获取函数参数类型
declare function f1(arg: { a: number; b: string }): void;
type T3 = Parameters<typeof f1>; // [{ a: number; b: string }]
// ConstructorParameters<T> - 获取构造函数参数类型
type T4 = ConstructorParameters<ErrorConstructor>; // [string]
// ReturnType<T> - 获取函数返回类型
type T5 = ReturnType<() => string>; // string
// InstanceType<T> - 获取构造函数实例类型
class C {
x = 0;
y = 0;
}
type T6 = InstanceType<typeof C>; // C
// ThisParameterType<T> - 提取函数 this 参数类型
function toHex(this: Number) {
return this.toString(16);
}
type T7 = ThisParameterType<typeof toHex>; // Number
// OmitThisParameter<T> - 移除函数 this 参数
type T8 = OmitThisParameter<typeof toHex>; // () => string
// ThisType<T> - 指定上下文类型
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // 在 methods 中,this 的类型是 D & M
};
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
let data: object = desc.data || {};
let methods: object = desc.methods || {};
return { ...data, ...methods } as D & M;
}
let obj2 = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // this 的类型被推断为 { x: number, y: number } & { moveBy: Function }
this.y += dy;
}
}
});
15. 异步编程
// Promise
function fetchData(): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data fetched successfully");
}, 1000);
});
}
// async/await
async function getData(): Promise<void> {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
}
// 多个 Promise
async function fetchMultiple(): Promise<[string, number]> {
const [data1, data2] = await Promise.all([
fetchData(),
Promise.resolve(42)
]);
return [data1, data2];
}
// Promise 类型工具
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
async function example() {
const result = await Promise.resolve(Promise.resolve(42));
type ResultType = Awaited<typeof result>; // number
}
总结
TypeScript 是 JavaScript 的超集,提供了以下核心特性:
- 静态类型系统:在编译时进行类型检查
- 类型推断:自动推断变量类型
- 接口和类型别名:定义复杂的数据结构
- 泛型:创建可重用的组件
- 装饰器:添加元数据和修改类行为
- 模块系统:更好的代码组织和封装
- 高级类型:条件类型、映射类型等
- 配置灵活:通过 tsconfig.json 精细控制编译选项
- 与现代 JavaScript 兼容:支持 ES6+ 所有特性
TypeScript 通过这些特性提高了代码的可维护性、可读性和开发效率,同时保持了与 JavaScript 的完全兼容性。