You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅提取继承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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:48:12