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

Apollo Server+TypeScript配置REST数据源时出现'any'类型不安全访问错误

解决Apollo Server REST数据源中的ESLint不安全访问错误

看起来你遇到的问题是TypeScript编译器能正确识别上下文类型,但ESLint的@typescript-eslint插件却误报了不安全访问的错误——这种情况其实挺常见的,主要是因为ESLint的类型检查逻辑和TypeScript语言服务的推断能力有细微差异。

错误原因分析

你的ResolverCtx类型是ApplicationContext & { dataSources: ApplicationDataSources },而ApplicationContext用了Record<string, any>。虽然TypeScript编辑器的语言服务能正确解析交叉类型,识别出ctx.dataSources的具体类型,但@typescript-eslint插件在处理包含any的交叉类型时,会倾向于把整个ctx对象的属性当成any类型看待,从而触发no-unsafe-member-access和no-unsafe-call错误。

解决方案

1. 优化上下文类型定义(推荐)

避免使用Record<string, any>这种宽泛的类型,换成明确的上下文属性定义。如果你的ApplicationContext没有额外属性,直接定义为空对象即可:

// resolver-ctx.ts
import MyRestDataSource from '../datasources/my-rest-datasource';

// 替换Record<string, any>为明确的类型,没有额外属性就用{}
type ApplicationContext = {};
// 如果有实际需要的上下文属性,比如用户信息,可以这样定义:
// type ApplicationContext = { user?: { id: string; name: string } };

type ApplicationDataSources = {
  myRestDataSource: MyRestDataSource;
};
type ResolverCtx = ApplicationContext & { dataSources: ApplicationDataSources };

export default ResolverCtx;

这种方式从根源上消除了any类型的干扰,ESLint就能正确识别ctx的类型了。

2. 给上下文添加类型断言

如果你确实需要保留Record<string, any>,可以在 resolver 里给ctx添加类型断言,明确告诉ESLint它的真实类型:

// myResolvers.ts
import { Resolvers } from 'types/codegen';
import ResolverCtx from 'types/resolver-ctx';

const myResolvers: Resolvers<ResolverCtx> = {
  Query: {
    getData: async (_, { id }, ctx) => {
      // 明确断言ctx的类型为ResolverCtx
      const typedCtx = ctx as ResolverCtx;
      return await typedCtx.dataSources.myRestDataSource.myGetMethod(id);
    }
  },
};

export default myResolvers;

3. 局部禁用ESLint规则(不推荐,仅应急使用)

如果以上两种方式都不适用,可以在报错的代码行局部禁用对应的ESLint规则,但这只是临时 workaround,不推荐长期使用:

// myResolvers.ts
import { Resolvers } from 'types/codegen';
import ResolverCtx from 'types/resolver-ctx';

const myResolvers: Resolvers<ResolverCtx> = {
  Query: {
    getData: async (_, { id }, ctx) => {
      // 临时禁用这两个规则
      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
      return await ctx.dataSources.myRestDataSource.myGetMethod(id);
    }
  },
};

export default myResolvers;

为什么编辑器能显示正确类型?

这是因为TypeScript的语言服务(编辑器用来提供类型提示的功能)比ESLint的@typescript-eslint插件更擅长解析复杂的交叉类型。它能忽略Record<string, any>的宽泛性,正确识别出交叉后的完整类型,但ESLint的规则检查会更严格地对待any类型的存在,从而产生误报。

内容的提问来源于stack exchange,提问作者Antfish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 00:09:08