关于 typescript-advanced
面向 TypeScript 开发者的高级类型参考技能,提供泛型、条件类型与映射类型、联合类型、类型守卫和工具类型组合的示例与注意事项。
主要功能
- 01带约束的泛型
- 02条件类型与映射类型
- 03可辨识联合类型
- 04类型守卫
- 05工具类型组合
- 06类型安全检查清单
适用场景
- 01为可复用泛型函数定义类型
- 02建模结果与状态的不同分支
- 03验证运行时的不确定值
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ rohitg00/ awesome-claude-code-toolkit --skill typescript-advanced安装后在 Claude Code 中输入/typescript-advanced确认已加载。
详细介绍
TypeScript 高级
带约束的泛型
interface HasId {
id: string;
}
function findById<T extends HasId>(items: T[], id: string): T | undefined {
return items.find(item => item.id === id);
}
function groupBy<T, K extends string | number>(
items: T[],
keyFn: (item: T) => K
): Record<K, T[]> {
return items.reduce((acc, item) => {
const key = keyFn(item);
(acc[key] ??= []).push(item);
return acc;
}, {} as Record<K, T[]>);
}
type ApiResponse<T> = {
data: T;
meta: { page: number; total: number };
};
async function fetchApi<T>(url: string): Promise<ApiResponse<T>> {
const res = await fetch(url);
return res.json();
}
条件类型
type IsString<T> = T extends string ? true : false;
type Flatten<T> = T extends Array<infer U> ? U : T;
type UnwrapPromise<T> = T extends Promise<infer U> ? UnwrapPromise<U> : T;
type FunctionReturn<T> = T extends (...args: any[]) => infer R ? R : never;
type ExtractRouteParams<T extends string> =
T extends `${string}:${infer Param}/${infer Rest}`
? Param | ExtractRouteParams<Rest>
: T extends `${string}:${infer Param}`
? Param
: never;
type Params = ExtractRouteParams<"/users/:userId/posts/:postId">;
映射类型
type Readonly<T> = { readonly [K in keyof T]: T[K] };
type Optional<T> = { [K in keyof T]?: T[K] };
type Nullable<T> = { [K in keyof T]: T[K] | null };
type PickByType<T, V> = {
[K in keyof T as T[K] extends V ? K : never]: T[K];
};
interface User {
id: string;
name: string;
age: number;
active: boolean;
}
type StringFields = PickByType<User, string>;
type EventMap<T> = {
[K in keyof T as `on${Capitalize<string & K>}`]: (value: T[K]) => void;
};
type UserEvents = EventMap<{ login: User; logout: string }>;
可辨识联合
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
function divide(a: number, b: number): Result<number, string> {
if (b === 0) return { ok: false, error: "Division by zero" };
return { ok: true, value: a / b };
}
const result = divide(10, 2);
if (result.ok) {
console.log(result.value);
} else {
console.error(result.error);
}
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rect"; width: number; height: number }
| { kind: "triangle"; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle": return Math.PI * shape.radius ** 2;
case "rect": return shape.width * shape.height;
case "triangle": return 0.5 * shape.base * shape.height;
}
}
类型守卫
function isNonNull<T>(value: T | null | undefined): value is T {
return value != null;
}
function hasProperty<K extends string>(
obj: unknown,
key: K
): obj is Record<K, unknown> {
return typeof obj === "object" && obj !== null && key in obj;
}
const values = [1, null, 2, undefined, 3].filter(isNonNull);
function assertNever(value: never): never {
throw new Error(`Unexpected value: ${value}`);
}
工具类型组合
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
type StrictOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &
{ [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>> }[Keys];
type UpdateUserInput = RequireAtLeastOne<{ name: string; email: string; age: number }>;
反模式
- 对于类型不确定的值,使用
any而不是unknown - 在类型守卫更安全时使用类型断言(
as) - 泛型签名过于复杂,降低可读性
- 对状态机或结果类型不使用可辨识联合
- 字符串字面量联合类型足以满足需求时仍使用
enum - 在 tsconfig 中忽略
strictNullChecks
检查清单
- 在 tsconfig 中启用
strict: true - 对外部数据使用
unknown而不是any - 类型守卫安全地验证运行时类型
- 使用可辨识联合建模状态,并通过穷尽式 switch 处理所有情况
- 泛型约束(
extends)可防止误用 - 使用映射类型从源类型派生相关类型
- 优先使用工具类型(
Pick、Omit、Partial),而不是手动重新定义类型 - 使用模板字面量类型强制执行字符串模式
评论
支持 Markdown