如何仅提取继承Record<string, unknown>的接口中显式定义的属性?
提取NextAuth JWT接口中的显式定义属性
背景
next-auth/jwt 提供的接口定义如下:
export interface DefaultJWT extends Record<string, unknown> { name?: string | null email?: string | null picture?: string | null sub?: string } export interface JWT extends Record<string, unknown>, DefaultJWT {}
我需要仅提取其中显式定义的属性(name、email、picture和sub)来扩展自定义类型。
尝试过的方法及问题
- 使用
Pick<JWT, keyof JWT>的写法:
import { JWT } from 'next-auth/jwt' export interface DefaultMyJWT { user_id: string user_role: string org_id: string org_slug: string } export type MyJwt = Pick<JWT, keyof JWT> & DefaultMyJWT
结果得到的类型几乎和JWT完全一致,原因是JWT继承了Record<string, unknown>,导致keyof JWT等价于keyof string,所有字符串键都被包含进来。
- 手动指定属性的写法:
export type MyJwt = Pick<JWT, 'name' | 'email' | 'picture' | 'sub'> & DefaultMyJWT
这种写法虽然可行,但存在弊端:如果next-auth包中的JWT接口发生变更(比如新增/移除显式属性),需要手动修改代码,TypeScript无法自动识别这类变更。
解决方案
可以通过TypeScript条件类型工具,自动提取接口中显式声明的属性,同时排除索引签名带来的影响:
import { DefaultJWT } from 'next-auth/jwt' export interface DefaultMyJWT { user_id: string user_role: string org_id: string org_slug: string } // 工具类型:过滤掉接口的索引签名,仅保留显式声明的键 type ExplicitKeys<T> = { [K in keyof T]: string extends K ? never : number extends K ? never : K }[keyof T] // 提取DefaultJWT中的所有显式属性 type ExplicitJWT = Pick<DefaultJWT, ExplicitKeys<DefaultJWT>> // 组合自定义JWT类型 export type MyJwt = ExplicitJWT & DefaultMyJWT
原理说明
ExplicitKeys<T>会遍历接口的每个键:如果键属于string或number类型(对应Record<string, unknown>的索引签名),就标记为never,最终只保留显式声明的键名。- 直接基于
DefaultJWT处理而非JWT,是因为DefaultJWT本身已经包含所有需要的显式属性,这样可以避免JWT双重继承带来的干扰。
后续如果next-auth更新DefaultJWT的显式属性,MyJwt会自动同步变更,无需手动修改代码。
内容的提问来源于stack exchange,提问作者Emad Omar
相关产品推荐
相关产品推荐

