【问题标题】:Typescript Namespace reference not working打字稿命名空间参考不起作用
【发布时间】:2021-09-20 23:19:11
【问题描述】:

我正在尝试使用 typescript 命名空间。当我不导入其他模块时它工作得很好,但是当我在我的情况下导入其他模块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`)
        }
    }
}

【问题讨论】:

    标签: javascript typescript class namespaces typescript-typings


    【解决方案1】:

    当您将 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 即可解决问题

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

    【讨论】:

    • 我一直在寻找这个问题的解决方案,但我什么也得不到。这个答案对我有很大的帮助。
    猜你喜欢
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2021-02-01
    • 2017-11-13
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    相关资源
    最近更新 更多