Typescript 如何防止隐藏全局接口?

Typescript 如何防止隐藏全局接口?,typescript,interface,shadowing,Typescript,Interface,Shadowing,我偶然发现Typescript中“隐藏”全局接口的问题: 即以下代码拒绝键入检查: 接口位置{ 位置:字符串; } 名为{ 名称:字符串; } 接口名DLOC扩展名为,位置{ s:字符串; } 让dd:NamedLoc={ s:‘3’, 名称:“asasf”, 地点:“asd” }; 出现以下错误: error TS2322: Type '{ s: string; name: string; location: string; }' is not assignable to type 'Na

我偶然发现Typescript中“隐藏”全局接口的问题:

即以下代码拒绝键入检查:

接口位置{
位置:字符串;
}
名为{
名称:字符串;
}
接口名DLOC扩展名为,位置{
s:字符串;
}
让dd:NamedLoc={
s:‘3’,
名称:“asasf”,
地点:“asd”
};
出现以下错误:

error TS2322: Type '{ s: string; name: string; location: string; }' is not assignable to type 'NamedLoc'.
  Property 'hash' is missing in type '{ s: string; name: string; location: string; }'.

13 let dd: NamedLoc = {
       ~~
注意,我定义了我自己的位置接口, 但是typescript以某种方式将位置接口的定义从:

interface Location {
    hash: string;
    host: string;
    hostname: string;
    href: string;
    readonly origin: string;
    pathname: string;
    port: string;
    protocol: string;
    search: string;
    assign(url: string): void;
    reload(forcedReload?: boolean): void;
    replace(url: string): void;
    toString(): string;
}
但是,这是类型检查

接口位置{
位置:字符串;
}
名为{
名称:字符串;
}
接口NamedLoc扩展名为Loc{
s:字符串;
}
让dd:NamedLoc={
s:‘3’,
名称:“asasf”,
地点:“asd”
};
我花了一些时间才发现这里没有使用我定义的类型,但肯定还有其他事情,因为甚至我的编辑器也跳入了本地定义接口的定义中

如果将来会引入另一个全局类型,而该类型恰好与我当前应用中的某个类型同名,会发生什么?它不再进行打字检查了吗

为什么会是这样,斯肯斯背后发生了什么

PS I正在跟踪TS文档:


下面是你所看到的情况的解释。可以用这个简短的例子重现它

interface Location {
    location: string;
}

// Error!
const loc: Location = {
    location: ''
}
你正在经历的是

因此,如果您的
位置
接口是全局的,它将添加到作为
lib.d.ts
一部分的现有
位置
接口

您可以通过模块或名称空间来避免这种情况:

namespace Example {
    interface Location {
        location: string;
    }

    // This works
    const loc: Location = {
        location: ''
    }
}

如果您的文件导入或导出,那么它将是一个模块,不会出现问题,就像在命名空间示例中一样。

这里发生的是接口声明合并,没有显示,实际上是扩展内置类型的基本机制。如果在全局范围中定义接口,则无法防止这种情况

您遇到的问题是clasic Javascript问题,即所有内容都在全局名称空间中。这个问题的解决方案是使用模块,这个解决方案同样适用于Typescript。如果您使用模块,您的接口将不会与全局接口合并


另一种解决方案是再次将所有代码放在专用名称空间中,以避免合并行为

谢谢你的回复!刚发布完这个,我就开始搜索,我发现了这个。。。这解释了一切!