Pressidian
花园入口
笔记
项目
关于
实验室
GitHub
花园入口
笔记
项目
关于
实验室
GitHub

KNOWLEDGE PATHS

笔记库
当前位置
笔记库/前端/项目笔记/代达罗斯/模式/StoryBook

组件的content

1 分钟阅读 · Note

目录树 578 篇

              • 组件的content
            • 表单最佳实践指南
            • 双层级导航结构
            • 以schema为中心的
            • 异步三态切换
            • 用neverthrow进行错误处理
            • Anatomy
            • cn
            • LoadingState&useList的组合
            • procedure中的service位置
            • scrollbar-gutter
            • TailwindCSS
            • TanStack Router 路由模式
            • useDebounce
            • useForm
            • void
          • 项目待做
          • 性能优化
          • UI设计
      • 前端技术栈
    • 笔记目录
    • CLAUDE.md
    • Vue 组件与 Render 函数

关联笔记 6

↗表单最佳实践指南共同主题↗双层级导航结构共同主题↗以schema为中心的共同主题↗异步三态切换共同主题↗用neverthrow进行错误处理共同主题↗Anatomy共同主题

这里的 = 表示:给泛型参数设置默认类型。

<TData extends BaseRecord = BaseRecord>

可以拆成两部分看:

TData extends BaseRecord

表示 TData 必须符合 BaseRecord 的结构约束。

TData = BaseRecord

表示调用时如果没有显式指定 TData,就默认使用 BaseRecord。

所以完整含义是:

> TData 必须是 BaseRecord 或它的子类型;如果调用者没有传类型,就把 TData 当作 BaseRecord。

例如:

type BaseRecord = {
  id: string;
};

type User = {
  id: string;
  name: string;
};

显式传入类型:

getList<User>();

此时:

TData = User

返回值就是:

Promise<GetListResponse<User>>

不传类型:

getList();

此时使用默认值:

TData = BaseRecord

返回值相当于:

Promise<GetListResponse<BaseRecord>>

如果没有这个默认值:

async <TData extends BaseRecord>(): Promise<GetListResponse<TData>>

调用 getList() 时,TypeScript 需要尝试推断 TData。但这个函数没有参数可以帮助推断,最终类型可能比较宽泛或者不符合库作者期望。

加上默认值后:

<TData extends BaseRecord = BaseRecord>

就明确告诉 TypeScript:推断不出来时,直接使用 BaseRecord。

你的完整代码可以理解为:

getList: async <
  TData extends BaseRecord = BaseRecord
>(): Promise<GetListResponse<TData>> => ({
  data: snippets as unknown as TData[],
  total: snippets.length,
}),

其中:

Promise<GetListResponse<TData>>

表示返回的数据结构中的 data 最终应该是:

TData[]

因此可以简单记住:

<T extends A = B>

含义是:

extends A:T 必须满足 A 的约束
= B:没有指定 T 时,默认使用 B

这里刚好默认值和约束类型一样:

<TData extends BaseRecord = BaseRecord>

但它们也可以不同:

type Animal = {
  name: string;
};

type Dog = Animal & {
  bark(): void;
};

function createAnimal<T extends Animal = Dog>(): T {
  // ...
}

这里 T 必须属于 Animal 范围,但默认使用 Dog。