目录
[一、class 类](#一、class 类)
[1. 基本语法](#1. 基本语法)
[2. 继承](#2. 继承)
[3. 可见性修饰符](#3. 可见性修饰符)
[4. 只读属性](#4. 只读属性)
[5. 参数属性(简化写法)](#5. 参数属性(简化写法))
[1. 泛型函数](#1. 泛型函数)
[2. 泛型约束](#2. 泛型约束)
[3. 泛型接口](#3. 泛型接口)
[4. 泛型类](#4. 泛型类)
[5. 泛型约束与默认类型](#5. 泛型约束与默认类型)
[6. 内置泛型工具类型](#6. 内置泛型工具类型)
[八、条件类型(Conditional Types)](#八、条件类型(Conditional Types))
[九、类型守卫(Type Guards)](#九、类型守卫(Type Guards))
[1. typeof 类型守卫](#1. typeof 类型守卫)
[2. in 操作符](#2. in 操作符)
[3. instanceof](#3. instanceof)
[4. 自定义类型守卫](#4. 自定义类型守卫)
本文介绍了TypeScript的核心类型系统特性。主要内容包括:
1)类的定义与继承、可见性修饰符和只读属性;
2)结构化类型兼容规则;
3)交叉类型与接口继承的区别;
4)泛型在函数、接口和类中的应用;
5)索引签名和映射类型;
6)条件类型和类型守卫机制。重点讲解了泛型工具类型(如Partial、Pick等)的使用方法,以及如何通过类型守卫缩小变量类型范围。
这些特性共同构成了TypeScript强大的静态类型系统,能够有效提升代码质量和开发体验。
一、class 类
1. 基本语法
TypeScript
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): void {
console.log(`Hello, I'm ${this.name}`);
}
}
2. 继承
TypeScript
class Student extends Person {
grade: number;
constructor(name: string, age: number, grade: number) {
super(name, age);
this.grade = grade;
}
study(): void {
console.log(`${this.name} is studying`);
}
}
3. 可见性修饰符
-
public:默认,任何地方都可访问 -
protected:当前类和子类可访问 -
private:仅当前类可访问
TypeScript
class Animal {
public name: string;
protected age: number;
private secret: string;
constructor(name: string) {
this.name = name;
}
}
4. 只读属性
TypeScript
class Person {
readonly id: number = 1;
constructor(id: number) {
this.id = id; // 只能在构造函数中赋值
}
}
5. 参数属性(简化写法)
TypeScript
class Person {
constructor(public name: string, private age: number) {}
}
// 自动创建 name 和 age 属性并赋值
二、类型兼容性
TypeScript 采用结构化类型系统(duck typing),只关心类型形状是否匹配。
TypeScript
class Point {
x: number;
y: number;
}
class Point2D {
x: number;
y: number;
}
let p: Point = new Point2D(); // ✅ 结构相同
函数兼容性:参数少的可以赋值给参数多的,返回值多的可以赋值给返回值少的。
TypeScript
type F1 = (a: number) => void;
type F2 = (a: number, b: number) => void;
let f1: F1;
let f2: F2 = f1; // ✅ 参数少的可以赋值给参数多的
三、交叉类型(&)
交叉类型将多个类型合并为一个。
TypeScript
type Person = { name: string };
type Contact = { phone: string };
type PersonDetail = Person & Contact; // { name: string; phone: string }
交叉类型 vs 接口继承
-
接口继承会检查同名属性类型是否兼容,不兼容会报错。
-
交叉类型直接合并,同名属性会形成交叉类型(如
string & number变成never)。
四、泛型(Generics)
泛型允许我们在定义函数、接口、类时不预先指定具体类型,而是在使用时再确定。
1. 泛型函数
TypeScript
function identity<T>(value: T): T {
return value;
}
// 显式指定类型
identity<number>(10);
// 类型推断
identity("hello");
2. 泛型约束
TypeScript
interface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(value: T): T {
console.log(value.length);
return value;
}
logLength("hello"); // ✅ 字符串有 length
logLength([1, 2, 3]); // ✅ 数组有 length
logLength(10); // ❌ 数字没有 length
3. 泛型接口
TypeScript
interface KeyValue<T, U> {
key: T;
value: U;
}
let kv: KeyValue<number, string> = { key: 1, value: "one" };
4. 泛型类
TypeScript
class Box<T> {
private content: T;
constructor(value: T) {
this.content = value;
}
get(): T {
return this.content;
}
}
let box = new Box<string>("hello");
5. 泛型约束与默认类型
TypeScript
function createArray<T = string>(length: number, value: T): T[] {
return Array(length).fill(value);
}
6. 内置泛型工具类型
| 工具类型 | 作用 |
|---|---|
Partial<T> |
所有属性变为可选 |
Required<T> |
所有属性变为必选 |
Readonly<T> |
所有属性变为只读 |
Pick<T, K> |
选取部分属性 |
Omit<T, K> |
排除部分属性 |
Record<K, T> |
构造对象类型 |
Exclude<T, U> |
从 T 中排除 U |
Extract<T, U> |
从 T 中提取 U |
NonNullable<T> |
排除 null 和 undefined |
ReturnType<T> |
获取函数返回类型 |
TypeScript
type Props = { id: number; title: string; completed: boolean };
type PartialProps = Partial<Props>;
type RequiredProps = Required<Props>;
type PickProps = Pick<Props, "id" | "title">;
type OmitProps = Omit<Props, "completed">;
type RecordObj = Record<"a" | "b", string>;
五、索引签名类型
用于定义对象可以包含任意属性。
TypeScript
interface StringMap {
[key: string]: string;
}
let obj: StringMap = { a: "1", b: "2", c: "3" };
六、映射类型
基于旧类型创建新类型,常用于工具类型的实现。
TypeScript
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
七、索引查询类型(索引访问类型)
通过索引访问获取属性类型。
TypeScript
type Props = { a: number; b: string };
type TypeA = Props["a"]; // number
type Union = Props["a" | "b"]; // number | string
type All = Props[keyof Props]; // number | string
八、条件类型(Conditional Types)
TypeScript
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<number>; // false
九、类型守卫(Type Guards)
1. typeof 类型守卫
TypeScript
function printAll(strs: string | string[] | null) {
if (typeof strs === "object") {
// 这里 strs 类型为 string[] | null
for (const s of strs) { // ❌ 可能为 null
}
}
}
2. in 操作符
TypeScript
interface A { a: number; }
interface B { b: string; }
function test(obj: A | B) {
if ("a" in obj) {
// obj 是 A
} else {
// obj 是 B
}
}
3. instanceof
TypeScript
function isDate(value: any): value is Date {
return value instanceof Date;
}
4. 自定义类型守卫
TypeScript
function isString(value: any): value is string {
return typeof value === "string";
}