打字稿命名空间参考不起作用

Typescript Namespace reference not working

我正在尝试使用打字稿命名空间。当我不导入其他模块时它工作得很好但是当我在我的例子中导入其他模块时 sort 导出的函数 get 不能在其他文件中使用,即使它们在同一个命名空间中。

import { sort } from "../sort"

namespace Api {
    export async function get(url:string){
        const res = await fetch("api/"+url)
        return await res.json()
    }
    export class Users {
        private uid: string
        constructor(uid: string){
            this.uid = uid
        }
        public async getUserProfile(){
            return await get(`/u/${this.uid}/profile`)
        }
        public async getUserSongs(){
            return await get(`/u/${this.uid}/musics`)
        }
    }
}

/// <reference path="api.ts" />

namespace Api {
    export class Track{
        private track_id: string
        constructor(track_id){
            this.track_id = track_id
        }
        public async hasLiked(){
            return await get("/track/"+this.track_id+"/hasLiked")
        }
    }
}

它说 could not find name get

但是当我不导入时 sort 它工作得很好

namespace Api {
    export async function get(url:string){
        const res = await fetch("api/"+url)
        return await res.json()
    }
    export class Users {
        private uid: string
        constructor(uid: string){
            this.uid = uid
        }
        public async getUserProfile(){
            return await get(`/u/${this.uid}/profile`)
        }
        public async getUserSongs(){
            return await get(`/u/${this.uid}/musics`)
        }
    }
}

当您将 import 语句添加到文件时,它会将 .ts 文件变成一个模块,并将文件中的所有声明“移动”到该模块的范围内。

因此 namespace Api 在其模块定义之外不可见,并将其从全局命名空间中删除。有几种处理方法:

  1. 您可以将主 Api 文件转换为定义文件,方法是将其扩展名更改为 d.ts 并将 namespace Api 换成 declare global {}。这样你甚至不需要三重斜杠导入,它仍然可以在全球范围内使用。您的新 api.d.ts 应如下所示:

import { sort } from "./sort";

declare global {
  namespace Api {
    export async function get(url: string) {
      const res = await fetch("api/" + url);
      return await res.json();
    }
    export class Users {
      private uid: string;
      constructor(uid: string) {
        this.uid = uid;
      }
      public async getUserProfile() {
        return await get(`/u/${this.uid}/profile`);
      }
      public async getUserSongs() {
        return await get(`/u/${this.uid}/musics`);
      }
    }
  }
}

  1. 省略顶级导入并像这样使用动态导入:

namespace Api {
  export async function get(url: string) {
    const sort = await import("./sort");
    const res = await fetch("api/" + url);
    return await res.json();
  }
  export class Users {
    private uid: string;
    constructor(uid: string) {
      this.uid = uid;
    }
    public async getUserProfile() {
      return await get(`/u/${this.uid}/profile`);
    }
    public async getUserSongs() {
      return await get(`/u/${this.uid}/musics`);
    }
  }
}

  1. 只需将 namespace ApiTrack 转换为 d.ts 即可解决问题

在打字稿中使用声明合并和模块非常复杂,我认为仍然有很多解决方法和陷阱,所以我的答案肯定可以扩展。