1. ?. --- 可选链(Optional Chaining)
安全访问深层属性,如果中间任意一层为 null 或 undefined,直接返回 undefined 而不报错。
ts
const name = user?.profile?.name;
// 传统写法等价于:
const name = user && user.profile && user.profile.name;
// 用于方法调用
obj?.method?.();
2. ?? --- 空值合并运算符(Nullish Coalescing)
当左侧值为 null 或 undefined 时,使用右侧默认值。与 || 的区别在于 || 会把 0、''、false 也视为假值。
ts
const a = null ?? 'default'; // 'default'
const b = 0 ?? 'default'; // 0(0 不是 null/undefined)
const c = '' ?? 'default'; // ''(空字符串不是 null/undefined)
const d = false ?? true; // false
// 对比 || 的行为:
const e = 0 || 'default'; // 'default'(0 被视为假值)
3. ?. + ?? 组合使用
ts
const name = user?.profile?.name ?? '匿名用户';
4. ?. --- 可选元素访问(Optional Element Access)
用于可能不存在的数组索引。
ts
const arr: (string | undefined)[] = ['a', 'b'];
const item = arr?.[5]; // undefined,不会报错
5. ?. --- 可选调用(Optional Call)
仅在函数存在时才调用。
ts
const fn: (() => void) | undefined = condition ? () => {} : undefined;
fn?.(); // 如果 fn 是 undefined,不会报错
6. ! --- 非空断言(Non-null Assertion)
断言表达式结果不为 null 或 undefined,告诉 TypeScript 编译器"我保证这里有值"。使用时要确保确实有值,否则运行时可能出错。
ts
const el = document.getElementById('app')!; // 断言一定存在
const name = user!.profile!.name;
7. ??= --- 逻辑空赋值(Logical Nullish Assignment)
仅在值为 null 或 undefined 时才赋值。
ts
let x: number | null = null;
x ??= 10; // x 变为 10
let y: number | null = 5;
y ??= 10; // y 保持 5,因为不是 null/undefined
8. ?.= --- 可选链赋值(Optional Chaining Assignment,ES2021)
通过可选链访问并赋值。
ts
obj?.prop = 'value';
// 等价于:if (obj) { obj.prop = 'value'; }
9. ||= --- 逻辑或赋值(Logical OR Assignment)
在值为假值 (null、undefined、0、''、false、NaN)时赋值。
ts
let x = 0;
x ||= 10; // x 变为 10(0 是假值)
10. &&= --- 逻辑与赋值(Logical AND Assignment)
仅当当前值为真值时才赋值。
ts
let x = 'hello';
x &&= 'world'; // x 变为 'world'
let y: string | null = null;
y &&= 'world'; // y 保持 null
11. ... --- 展开运算符(Spread Operator)
对象展开:
ts
const a = { x: 1, y: 2 };
const b = { ...a, z: 3 }; // { x: 1, y: 2, z: 3 }
数组展开:
ts
const arr1 = [1, 2];
const arr2 = [3, 4];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]
函数参数展开:
ts
const nums = [1, 2, 3];
Math.max(...nums); // 3
剩余参数:
ts
function fn(a: string, ...rest: number[]) {
console.log(a, rest); // 'hi', [1, 2, 3]
}
fn('hi', 1, 2, 3);
12. ... --- 剩余属性(Rest Properties)
ts
const { x, ...remaining } = { x: 1, y: 2, z: 3 };
// x = 1, remaining = { y: 2, z: 3 }
13. : --- 类型注解(Type Annotation)
声明变量、函数参数、返回值的类型。
ts
const name: string = 'Tom';
function add(a: number, b: number): number {
return a + b;
}
14. as --- 类型断言(Type Assertion)
强制告诉编译器某个值的具体类型。
ts
const value: unknown = 'hello';
const str = value as string;
// 在 JSX 中需用 <>
const el = document.getElementById('app') as HTMLElement;
15. keyof --- 索引类型查询(Index Type Query)
获取类型的所有属性名组成的联合类型。
ts
type User = { name: string; age: number };
type UserKeys = keyof User; // 'name' | 'age'
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
16. typeof --- 类型查询
获取变量的类型。
ts
const config = { theme: 'dark', lang: 'zh' };
type Config = typeof config; // { theme: string; lang: string }
17. infer --- 条件类型中的类型推断
在条件类型中推断某个类型的位置。
ts
// 提取数组元素的类型
type ElementType<T> = T extends (infer U)[] ? U : never;
type A = ElementType<string[]>; // string
// 提取函数返回值的类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
18. & --- 交叉类型(Intersection Types)
合并多个类型。
ts
type A = { x: number };
type B = { y: string };
type C = A & B; // { x: number; y: string }
19. | --- 联合类型(Union Types)
表示值可以是多种类型之一。
ts
let id: string | number;
id = 'abc'; // OK
id = 123; // OK
id = true; // Error
20. readonly --- 只读修饰符
防止属性被修改。
ts
type Point = {
readonly x: number;
readonly y: number;
};
const p: Point = { x: 1, y: 2 };
p.x = 5; // Error: Cannot assign to 'x' because it is a read-only property
21. # --- 私有字段(Private Class Fields)
ES2020 / TypeScript 3.8 引入的真正私有字段,比 private 更严格,无法在类外访问,也无法被子类访问。
ts
class Counter {
#count: number = 0; // 真正的私有字段
inc() {
this.#count++;
}
getValue() {
return this.#count;
}
}
const c = new Counter();
c.#count; // Error: Private field '#count' must be declared in an enclosing class
22. asserts --- 断言函数(Assertion Functions)
断言函数确保在返回时某个条件必定成立。
ts
function assertIsString(val: unknown): asserts val is string {
if (typeof val !== 'string') {
throw new Error('Not a string!');
}
}
function process(val: unknown) {
assertIsString(val);
// 此后 val 被断言为 string,TS 允许直接当作字符串使用
console.log(val.toUpperCase());
}
23. satisfies --- 满足类型断言(satisfies Operator)
TypeScript 4.9 引入,验证值满足类型,同时保留字面量类型(不会拓宽)。
ts
type Color = 'red' | 'green' | 'blue';
type Config = { [key: string]: Color | Color[] };
// 不使用 satisfies:palette 被拓宽为 { [key: string]: ... }
const palette = {
red: [255, 0, 0],
green: '#00ff00',
} satisfies Config;
// 使用 satisfies:palette.red 的类型被保留为 [255, 0, 0](元组),palette.green 保留为 string
const redComponent = palette.red[0]; // TS 知道是数字
24. declare --- 声明(Declaration)
声明类型而不实现,常用于声明全局变量、模块、命名空间。
ts
declare const __DEV__: boolean;
declare module '*.svg' {
const content: string;
export default content;
}
25. enum --- 枚举
ts
enum Direction {
Up = 'UP',
Down = 'DOWN',
}
// 编译后为:
// const Direction = { Up: 'UP', Down: 'DOWN', Up: 'UP', Down: 'DOWN' };
// const Direction = { 0: 'Up', 1: 'Down', Up: 0, Down: 1 };
26. 模板字面量类型(Template Literal Types)
用反引号定义基于字符串字面量的类型。
ts
type EventName = 'click' | 'focus' | 'blur';
type Handler = `on${Capitalize<EventName>}`;
// Handler = 'onClick' | 'onFocus' | 'onBlur'
一图总结
| 符号 | 名称 | 用途 |
|---|---|---|
?. |
可选链 | 安全访问嵌套属性 |
?? |
空值合并 | ?? 仅对 null/undefined 生效 |
! |
非空断言 | 断言值不为 null/undefined |
??= |
空值赋值 | 仅在 null/undefined 时赋值 |
| ` | =` | |
&&= |
与赋值 | 在真值时赋值 |
... |
展开/剩余 | 合并或收集数据 |
keyof |
索引查询 | 获取类型的所有键 |
typeof |
类型查询 | 获取变量的类型 |
infer |
类型推断 | 条件类型中推断类型 |
& |
交叉类型 | 合并多个类型 |
as |
类型断言 | 强制转换类型 |
readonly |
只读 | 防止属性被修改 |
# |
私有字段 | 真正的类私有成员 |
asserts |
断言函数 | 断言某条件必定成立 |
satisfies |
满足断言 | 验证类型且保留字面量 |