前端React Nextjs中的TS类型过滤实用技巧
本文深入解析TypeScript中利用Pick、keyof及条件类型实现类型过滤的高级技巧。通过拆解FilterConditionally类型,讲解如何遍历对象属性并筛选指定类型,结合React源码实例,帮助开发者掌握静态类型校验的核心方法,提升代码质量与可维护性。
大家好,我是零一。在查阅同事代码或优秀开源库时,大家或许见过各种复杂的TS写法,若不花时间钻研很难理解。若由我们自己编写,可能直接选用any即可,但随着项目规模扩大,这些TS高级技巧的重要性便凸显出来,因为它们能高效协助完成静态类型校验。
自我介绍
TS类型过滤(英文名为FilterConditionally,此为笔者自创名称)的完整定义如下所示。
type FilterConditionally<Source, Condition> = Pick<
Source,
{
[K in keyof Source]: Source[K] extends Condition ? K : never
}[keyof Source]
>;
尽管该类型定义看似复杂,但实际应用价值极高。它能够从一个对象类型中精准筛选出符合特定条件的属性,例如:
interface Example {
a: string;
b: string;
c: number;
d: boolean;
}
type NewType = FilterConditionally<Sample, string>
/*
NewType 最终结果为:
{
a: string;
b: string
}
*/
相信读者已经了解了该类型的作用,并且渴望深入理解其原理。接下来,我们将由内而外、分步骤进行解析,确保大家能够完全掌握。若仍有疑问,欢迎在评论区交流(注:此为玩笑话)。
分步介绍
由于涉及的知识点较多,为避免不熟悉TS的读者感到困惑,我们先介绍其中几个常见的基础知识点。
开胃小菜
这部分内容不会占用太多时间,熟悉这些概念的读者可以直接跳过。
keyof
关键词keyof被称为索引类型查询操作符,其作用正如字面意思所示:获取对象的key值。
interface Example {
a: string;
b: string;
c: number;
d: boolean;
}
type Keys = keyof Example // 等价于 type Keys = 'a' | 'b' | 'c' | 'd'
可以将keyof简单理解为JavaScript中的Object.keys方法。
in
关键词in用于遍历枚举类型,具体示例如下:
type Keys = 'a' | 'b' | 'c' | 'd'
type Obj = {
[T in Keys]: string; // 遍历Keys,把每个key都赋值string类型
}
/* 等价于
type Obj = {
a: string;
b: string;
c: string;
d: string;
}
*/
可以将in简单理解为JavaScript中for...in循环里的in关键字的作用。
Conditional
第二个知识点是条件判断,例如:
interface A {}
interface B extends A {} // B继承于A
// B是否继承于A?若是,则为number类型;若不是,则为string类型
type C = B extends A ? number : string // 等价于 type C = number
// A是否继承于B?若是,则为number类型;若不是,则为string类型
type D = A extends B ? number : string // 等价于 type D = string
可以将A extends B ? number : string简单理解为JavaScript中的三元运算符。
泛型
关于泛型的详细介绍此处略过,不了解的读者可直接查阅TS文档中的泛型部分。
正餐开始
介绍完基础知识点后,趁热打铁来看一个简单的类型定义。
type MarkUnwantedTypesAsNever<Source, Condition> ={
[K in keyof Source]: Source[K] extends Condition ? K : never
}
一句话概括该类型的作用:遍历一个对象类型,将不符合条件的类型标记为never。
举个例子:
interface Example {
a: string;
b: string;
c: number;
d: boolean;
}
// 我只想要Example类型中的string类型的key,非string的就标记为never
type MyType = MarkUnwantedTypesAsNever<Example, string>
/*
等价于:
type MyType = {
a: 'a';
b: 'b';
c: never;
d: never;
}
*/
简要说明其中的细节:[K in keyof Example]遍历了Example对象类型,随后使用条件判断Source[K] extends Condition ? K : never为对应的key值赋值。假设遍历的第一个key值为a,那么Source[K] = Source[a] = string,此时即为string extends string ? 'a' : never。由于string确实继承于string,因此得到了上述结果。
此时读者可能会疑惑,为什么要将类型处理成这样?我们最终想要的结果不是获取一个包含特定key-value的对象类型吗?别急,后续还有其它操作。
再来看一个关于索引访问接口属性的小知识点。
type Value = {name: "zero2one"}["name"] // 等价于 type Value = "zero2one"
可以将其简单理解为JavaScript中访问对象某个key对应的value。
而在TS中还存在另一种情况:
type Value = {
name: "zero2one";
age: 23
}["name" | "age"]
// 等价于 type Value = "zero2one" | 23
值为never的key值是无法被访问到的:
type Value = {
name: "zero2one";
age: never
}["name" | "age"]
// 等价于 type Value = "zero2one"
因此,接下来可以查看更复杂的类型定义。
type MarkUnwantedTypesAsNever<Source, Condition> ={
[K in keyof Source]: Source[K] extends Condition ? K : never
}[keyof Source]
我们巧妙地利用keyof关键词去遍历访问所有的接口属性。
// 借用一下刚才例子的结果
type MyType = {
a: 'a';
b: 'b';
c: never;
d: never;
}['a' | 'b' | 'c' | 'd']
/*
等价于:
type MyType = 'a' | 'b'
*/
至此,我们所做的事情就是:把目标对象类型中符合指定类型的key值筛选了出来。
别急别急,离成功只差一步之遥。
最后登场的是Pick类型,这是TS内置的类型,简单了解一下它的作用。
// Pick类型的实现
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
你可以不去详细读懂它的实现,只需要知道Pick的作用就是:筛选出类型T中指定的某些属性。
举个简单的例子:
interface A {
a: 1;
b: 2;
c: 3;
d: 4;
}
type C = Pick<A, 'a' | 'c'> // 等价于 type C = { a: 1; c: 3 }
是的,就是这么简单。好了,可以来看最终的“Boss”了。

那么最后再从Source中筛选出对应属性即可。回到本文具体的例子当中,图中红框中的值上文已得到为type MyType = 'a' | 'b',那最后Pick一下就好了。
interface Example {
a: string;
b: string;
c: number;
d: boolean;
}
// 上文得到的结果
type MyType = 'a' | 'b'
type Result = Pick<Example, MyType> // 等价于 type Result = { a: string; b: string }
// ---- 以上等价于 ---- //
interface Example {
a: string;
b: string;
c: number;
d: boolean;
}
type NewType = FilterConditionally<Sample, string>
/*
NewType 最终结果为:
{
a: string;
b: string
}
*/
这就是文章开头的结果获取的全过程。
实战应用例子
正如本文标题所述,TS类型过滤在很多优秀的开源库中是非常常见的,比如我们熟悉的React中就是:
type ElementType<P = any> = {
[K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K] ? K : never
}[keyof JSX.IntrinsicElements] | ComponentType<P>;
最后
开源库中像TS类型过滤这种场景太多太多了,希望今后大家遇到时能轻松读懂。如果在屏幕前阅读的你是后端开发者,说不定也能在后端的开源框架源码中看到它的身影呢~
以上就是前端React Nextjs中的TS类型过滤实用技巧的详细内容,更多关于前端React Nextjs中的TS类型过滤的资料请关注本站其它相关文章!
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53








