整理一些好用的TS写法

1. 工具类型

Partial

所有的字段都会被成可选的

typescript 复制代码
interface AppConfig {
  title: string;
  version: number;
  theme: 'light' | 'dark';
}

type PartialConfig = Partial<AppConfig>;
// Equivalent to: { title?: string; version?: number; theme?: 'light' | 'dark'; }
Pick

从一个类型中选中指定属性

typescript 复制代码
interface AppConfig {
  title: string;
  version: number;
  theme: 'light' | 'dark';
}

type TitleConfig = Pick<AppConfig, 'title' | 'version'>;
// Equivalent to: { title: string; version: number; }
Omit

从一个类型中排除指定属性

typescript 复制代码
interface AppConfig {
  title: string;
  version: number;
  theme: 'light' | 'dark';
}

type WithoutTheme = Omit<AppConfig, 'theme'>;
// Equivalent to: { title: string; version: number; }
Readonly

将所有属性变为只读

typescript 复制代码
interface AppConfig {
  title: string;
  version: number;
  theme: 'light' | 'dark';
}

type ReadonlyConfig = Readonly<AppConfig>;
// Equivalent to: { readonly title: string; readonly version: number; readonly theme: 'light' | 'dark'; }
Required

将所有属性变为必选

typescript 复制代码
type RequiredConfig = Required<{
  description?: string | null;
}>;
// Equivalent to: { description: string | null; }

这里要注意:

description?: string | nulldescription: string | null | undefined 是不一样的。

前一个代表 description 是可选的,后一个代表 description 的值可能是 undefined

Required 只会移除 ?, 而不会去处理 undefined

ts 复制代码
type RequiredConfig = Required<{
  description: string | null | undefined;
}>;
// Equivalent to: {  description: string | null | undefined; }
Record

创建一个对象类型,键为指定的类型,值为指定的类型

ts 复制代码
type RecordConfig = Record<'vueApp' | 'ngApp', AppConfig>;
// Equivalent to: { vueApp: AppConfig; ngApp: AppConfig; }
Exclude

从联合类型中排除指定的类型

ts 复制代码
type ExcludeConfig = Exclude<'a' | 'b' | 'c', 'b' | 'd'>;
// Equivalent to: 'a' | 'c'
Extract

从联合类型中提取交集的类型

ts 复制代码
type ExtractConfig = Extract<'a' | 'b' | 'c', 'b' | 'd'>;
// Equivalent to: 'b'
NonNullable:

从联合类型中排除 null 和 undefined

ts 复制代码
type NonNullableUnitType = NonNullable<string | null | undefined>;
// Equivalent to: string

但是它无法对类型进行非空处理

ts 复制代码
type NonNullableType = NonNullable<{
  description: string | null | undefined;
}>;
// 你预期的结果: { description: string; }
// 实际结果: { description: string | null | undefined; }

可以基于 NonNullable Map一个新的工具类型,实现上述需求

ts 复制代码
type NonNullablePlus<T> = {
  [K in keyof T]: NonNullable<T[K]>;
};

type NonNullableType = NonNullablePlus<{
  description: string | null | undefined;
}>;
// Equivalent to: { description: string; }
Parameters

提取函数参数类型, 返回数组

ts 复制代码
declare function f1(arg: { a: number; b: string }, arg2: string): void;
type F1Parameters = Parameters<typeof f1>;
// Equivalent to: [arg: { a: number; b: string; }, arg2: string]

type T1 = Parameters<() => void>;
// Equivalent to: []
ConstructorParameters

提取类的构造函数参数, 返回数组

ts 复制代码
class C {
  constructor(a: number, b: string) {}
}
type TCConstructorParameters = ConstructorParameters<typeof C>;
// Equivalent to: [a: number, b: string]
ReturnType

提取函数返回值类型

ts 复制代码
declare function f1(): { a: number; b: string };;
type F1ReturnType = ReturnType<typeof f1>;
// Equivalent to: { a: number; b: string; }
InstanceType

提取类的类型

ts 复制代码
class C {
  x = 0;
  y = 0;
  constructor(a: number, b: string) {}
}
type CType = InstanceType<typeof C>;
// Equivalent to: C
NoInfer
  1. 强制用户显式的指定泛型类型
ts 复制代码
function useValue<T>(value: NoInfer<T>): T {
  return value;
}

const explicitValue = useValue<string>("hello"); // OK
const inferredValue = useValue("hello"); // Error: 必须显式的指定类型
  1. 防止泛型类型推断
ts 复制代码
function createStreetLight<C extends string>(
  colors: C[],
  defaultColor?: NoInfer<C>,
) {
  // ...
}
createStreetLight(["red", "yellow"], );  // OK
createStreetLight(["red", "yellow", "green"], "blue");  // Error

这里,NoInfer<C> 确保 defaultColor 的类型必须显式匹配 C,而不会被推断为其他类型。

  1. 防止默认类型被覆盖
ts 复制代码
function createStore<T = { default: true }>(state: NoInfer<T>): T {
  return state;
}

const store = createStore(); // 类型为 { default: true }
const customStore = createStore({ custom: true }); // Error: 类型推断被阻止

2. 模板字面量类型

它可以基于字符串模板创建类型。

Capitalize<StringType> 可以将字符串字面量类型的第一个字符转换为大写。

typescript 复制代码
type Event = 'click' | 'hover';
type EventHandler = `on${Capitalize<Event>}`;

const handler: EventHandler = 'onClick'; // 或 'onHover'

除了 Capitalize 外,还有其它几个

  • Uncapitalize<StringType> :将字符串字面量类型的第一个字符转换为小写。
  • Uppercase<StringType>:将字符串字面量类型的所有字符转换为大写。
  • Lowercase<StringType> :将字符串字面量类型的所有字符转换为小写。

你可以结合 keyof 自己创建一些更有用的工具类型

ts 复制代码
type UppercaseKeys<T> = {
  [K in keyof T as Uppercase<K & string>]: T[K];
};

type Example = UppercaseKeys<{ name: string; age: number }>;
// Equivalent to: { NAME: string; AGE: number }

3. keyof

3.1 获取对象类型的键

ts 复制代码
type Person = {
  name: string;
  age: number;
  isStudent: boolean;
};

type PersonKeys = keyof Person;
// Equivalent to: 'name' | 'age' | 'isStudent'

3.2 使用 keyof 限制键的类型

ts 复制代码
function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const person = { name: 'Alice', age: 25 };

const name = getValue(person, 'name'); // OK, 返回类型为 string
const age = getValue(person, 'age'); // OK, 返回类型为 number
// const invalid = getValue(person, 'height'); // Error: 类型 '"height"' 不可分配给参数

3.3 map 类型

可以用 Partial 作为例子

ts 复制代码
/**
 * Make all properties in T required
 */
type Required<T> = {
    [P in keyof T]-?: T[P];
};

这里 -? 的作用是从属性中移除可选标记(?)。它的作用是将类型中的所有可选属性变为必选属性。

4. infer

它用于条件中的类型推导。

Typescript 官网拿 ReturnType 这一经典例子来演示它的作用

ts 复制代码
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

如果 T 继承了 (...args: any[]) => any 类型,则返回类型 R,否则返回 any。其中的 R 是从传入参数类型中推导出来的,infer相当于一个类型占位。

可以结合上面 ReturnType 中的例子来看

ts 复制代码
declare function f1(): { a: number; b: string };;
type F1ReturnType = ReturnType<typeof f1>;
// Equivalent to: { a: number; b: string; }

5. as const

as const 将一个对象或数组的所有属性变为 只读 ,并将其值的类型从宽泛的类型(如 stringnumber)缩小为更具体的类型(如 'value'1)。

ts 复制代码
const data = { age: 1 };
type DataType =  typeof data;
// Equivalent to: { age: number; }

const dataConst = { age: 1 } as const;
type DataConstType =  typeof dataConst;
// Equivalent to: { readonly age: 1; }

它可以与 typeof 一起使用,从常量中提取更具体的类型。

ts 复制代码
const COLORS = {
  RED: 'red',
  GREEN: 'green',
  BLUE: 'bl?

type Color = typeof COLORS[keyof typeof COLORS];
// Equivalent to: 'red' | 'green' | 'blue'


const directions = ['up', 'down', 'left', 'right'] as const;

type Direction = typeof directions[number];
// Equivalent to: 'up' | 'down' | 'left' | 'right'

6. 泛型约束

通过 extends 关键字,可以对泛型进行约束,限制泛型的类型范围。

ts 复制代码
function getLength<T extends { length: number }>(arg: T): number {
  return arg.length;
}

getLength('Hello'); // OK, string 有 length 属性
getLength([1, 2, 3]); // OK, 数组有 length 属性
// getLength(42); // Error: number 没有 length 属性

7. 根据枚举值,动态生成类型

ts 复制代码
enum ShapeType {
    Square = 1,
    Circle = 2
}

interface Square {
    size: number;
}

interface Circle {
    radius: number;
}

type MutableRecord<T> = {
  [SubType in keyof T]: {
    type: SubType;
  } & { [K in keyof T[SubType]]: T[SubType][K] };
}[keyof T];

type Shape = MutableRecord<{
  [ShapeType.Square]: Square;
  [ShapeType.Circle]: Circle;
}>;

const circle: Shape = {
  type: ShapeType.Circle,
  radius: 1, // 这里只会出现 radius
};
const square: Shape = {
  type: ShapeType.Square,
  size: 1, // 这里只会出现 size
};

持续更新中...

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax