【问题标题】:TypeScript interface not recognized when in a .d.ts file在 .d.ts 文件中无法识别 TypeScript 接口
【发布时间】:2021-02-28 12:18:54
【问题描述】:

我们有一个文件包含tscvscode 无法识别的接口。

src/sap-truck-roster/resolver/RosterResolver.ts:40:17 - 错误 TS2304:找不到名称“上下文”。

// src\shared\types\Context.d.ts
import { Roster } from '@sap-truck-roster/entity/Roster'
import { Account } from '@it-portal/entity/Account'

 interface Context {
  user: Account
  dataSources: {
    sapRosterApi: Roster
  }
}

显然我们需要在tsconfig 中使用选项typeRoots,正如建议的here。但由于某种原因,接口Context 仍然无法识别。我们在这里缺少什么?

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@environment": ["src/environment"],
      "@utils/*": ["src/utils/*"]
    },
    "typeRoots": ["./node_modules/@types", "./src/shared/types/**/*.d.ts"],
    "rootDir": "./src",
    "outDir": "./dist",
    "target": "es6",
  },
  "exclude": ["node_modules"],
  "include": ["./src/**/*.tsx", "./src/**/*.ts", "./src/**/*.d.ts"]
}

使用界面:

import { Resolver, Arg, Query, Ctx, Field, ObjectType, createUnionType } from 'type-graphql'
import { Roster } from '@sap-truck-roster/entity/Roster'
import { plainToClass } from 'class-transformer'

@Resolver()
export class RosterResolver {
  @Query(() => RosterQueryResultUnion)
  async roster(
    @Ctx() ctx: Context,   // use Context without import
    @Arg('date', () => String) date: string
  ): Promise<typeof RosterQueryResultUnion> {
    const response = await ctx.dataSources.sapRosterApi.getRoster(date)

    if (response.returnCode === 'OK') {
      return plainToClass(RosterArray, {
        data: response.data,
      })
    }
    return plainToClass(ApiError, {
      code: response.returnCode,
      message: response.errorMessage,
    })
  }
}

【问题讨论】:

  • 为什么不导出?
  • 当使用 exportimport 时它工作正常。但是使用.d.ts文件的目的是不再需要这个,接口在全局范围内。
  • 你能具体说明你想如何访问这个界面吗?
  • 没问题,更新了 OP

标签: typescript tsconfig


【解决方案1】:

不进行导出会阻止 TS 发现它。

.d.ts 文件旨在声明或扩充命名空间/模块,同时禁止任何其他 TS 操作,因为它们是纯声明文件。

它们并不是为了避免使用导入/导出。

如果你想全局声明一个接口,你应该通过augmenting the global module这样做

在你的情况下

declare global {
  interface Context {
    user: Account
    dataSources: {
      sapRosterApi: Roster
    }
  }
}

但我强烈建议不要这样做,将来可能会让你很痛苦

对你来说,最好创建一个普通的.ts 文件并导出接口,然后将其导入其他地方。 如果这仍然不起作用,请检查 tsconfig 路径是否配置正确或切换到使用相对导入路径。

混淆typeRoots 选项通常还会禁用@types/* 包自动发现并导致无法调试的问题。

【讨论】:

    【解决方案2】:

    您可以使用模块声明来实现这一点。

    declare module SomeName {
        interface Context {
            user: Account
            dataSources: {
              sapRosterApi: Roster
            }
        }
    }
    
    

    现在可以直接这样写了。

    const ctx: SomeName.Context = {} // without importing anything
    

    更新 tsconfig.json
    "typeRoots": ["./node_modules/@types", "./src/shared/types/**/*.d.ts"],
    

    "typeRoots": ["./node_modules/@types", "./src/shared/types"],
    

    这必须有效。如果没有,请告诉我。

    代码沙盒:https://codesandbox.io/s/ecstatic-tdd-tb11c?file=/src/App.tsx

    【讨论】:

    • 这似乎是明智之举,但当我尝试时,我得到error TS2503: Cannot find namespace 'SomeName'.
    • 用您的建议更新tsconfig 后出现同样的问题。甚至厌倦了按照建议添加export here,没有运气。
    • 它必须有效。检查代码沙箱 URL。它只有一个 lint 问题,代码运行良好。
    【解决方案3】:

    只有在 .d.ts 文件中并且您没有从该 .d.ts 文件中的任何模块导入任何类型时,您才能在不导入的情况下使用类型或接口

    【讨论】:

      猜你喜欢
      • 2021-01-13
      • 2022-11-05
      • 2020-04-30
      • 1970-01-01
      • 2018-01-12
      • 2021-03-30
      • 2016-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多