问题描述
我正在尝试使用 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
解决方法
当您向文件中添加 import 语句时,它会将 .ts
文件转换为模块,并将文件中的所有声明“移动”到该模块的范围内。
因此 namespace Api
在其模块定义之外不可见,并将其从全局命名空间中删除。有几种处理方法:
- 您可以通过将主
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`);
}
}
}
}
- 省略顶级导入并像这样使用动态导入:
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`);
}
}
}
- 只需将
namespace Api
与Track
转换为d.ts
即可解决问题
在打字稿中使用声明合并和模块非常复杂,我认为仍然有很多解决方法和陷阱,所以我的答案肯定可以扩展。