Appearance
TypeScript 类型系统
TypeScript 的核心是其类型系统,它允许开发者在编译时定义和检查类型,从而减少运行时错误。
基本类型详解
原始类型
TypeScript 支持 JavaScript 的所有原始类型:
typescript
// 布尔值
let isCompleted: boolean = true;
// 数字(包括整数、浮点数、十六进制、八进制等)
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
// 字符串
let greeting: string = "Hello, world";
// 数组
let numbers: number[] = [1, 2, 3];
let numbers2: Array<number> = [1, 2, 3]; // 泛型语法
// 元组
let person: [string, number] = ["Alice", 25];
特殊类型
typescript
// 枚举
enum Direction {
Up = 1,
Down,
Left,
Right
}
let direction: Direction = Direction.Up;
// Any(任意类型)
let notSure: any = 4;
notSure = "maybe a string";
notSure = false;
// Void(无返回值)
function warnUser(): void {
console.log("This is a warning message");
}
// 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 });
对象类型
接口(Interface)
typescript
interface User {
name: string;
age: number;
email?: string; // 可选属性
}
let user: User = {
name: "John",
age: 30
};
类型别名(Type Alias)
typescript
type Point = {
x: number;
y: number;
};
type ID = string | number;
// 与接口的区别
type Window = {
// 不能重复定义
};
// 接口可以重复定义(合并)
interface Window {
title: string;
}
interface Window {
ts: number;
}
联合类型与交叉类型
联合类型
typescript
function formatId(id: number | string) {
return typeof id === "number" ? id.toString() : id;
}
// 类型守卫
function isString(value: unknown): value is string {
return typeof value === "string";
}
// 字面量类型
type Size = "small" | "medium" | "large";
type StatusCode = 200 | 400 | 404 | 500;
交叉类型
typescript
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
type ColorfulCircle = Colorful & Circle;
const circle: ColorfulCircle = {
color: "red",
radius: 5
};
泛型
typescript
// 泛型函数
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString");
let output2 = identity("myString"); // 类型推断
// 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
类型推断与类型断言
类型推断
typescript
// 基于初始化值的推断
let x = 3; // 推断为 number
// 基于上下文的推断
window.onmousedown = function(mouseEvent) {
console.log(mouseEvent.button); // 推断为 MouseEvent
};
类型断言
typescript
// 尖括号语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
// as 语法
let someValue2: any = "this is a string";
let strLength2: number = (someValue2 as string).length;
// 非空断言操作符
function liveDangerously(x?: number | null) {
console.log(x!.toFixed()); // 告诉 TS x 不是 null 或 undefined
}
高级类型
索引类型
typescript
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
return names.map(n => o[n]);
}
interface Person {
name: string;
age: number;
}
const person: Person = { name: "Jarid", age: 35 };
const values = pluck(person, ["name", "age"]);
映射类型
typescript
interface Person {
name: string;
age: number;
}
type ReadonlyPerson = Readonly<Person>;
type PartialPerson = Partial<Person>;
type PickPerson = Pick<Person, "name">;
type RecordPerson = Record<"a" | "b", Person>;
类型保护
typescript
// typeof 类型保护
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
// instanceof 类型保护
interface Padder {
getPaddingString(): string;
}
class SpaceRepeatingPadder implements Padder {
constructor(private numSpaces: number) {}
getPaddingString() {
return Array(this.numSpaces + 1).join(" ");
}
}
function usePadder(padder: Padder) {
if (padder instanceof SpaceRepeatingPadder) {
padder.numSpaces; // 在这个分支中,TypeScript 知道这是 SpaceRepeatingPadder
}
}
小结
TypeScript 的类型系统是其最强大的特性之一,通过合理使用各种类型,可以显著提高代码的健壮性和可维护性。掌握这些类型概念对于编写高质量的 TypeScript 代码至关重要。