当您浏览collections typings file时,您经常会看到模式:
interface Set<T> {
add(value: T): this;
clear(): void;
delete(value: T): boolean;
forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
has(value: T): boolean;
readonly size: number;
}
interface SetConstructor {
new (): Set<any>;
new <T>(values?: T[]): Set<T>;
readonly prototype: Set<any>;
}
declare var Set: SetConstructor;
即:
declare
我真的无法理解这一点。有人可以回答一些问题吗?
Set<T>
的目的很明确,但实际实施在哪里?当我致电new Set()
时,我实际创造了什么?在其他语言中,我不能实例化一个接口(它不是要实例化),而只是一个实现接口的类。declare var
部分是最令人困惑的事情:
declare
旨在引入在其他地方实现的类型。它如何用于变量?并且,import
(或require
)是否应该获得在其他地方实施的代码?Set
为名称,SetConstructor
为类型)让我摇头。实际上是什么?答案 0 :(得分:2)
(1) 所有不同的lib文件都描述了您将在其中运行脚本(浏览器/节点)的环境中已存在的本机对象和类。 这就是为什么你没有看到这些接口的实现。
(2)
所有使用Constructor
后固定的接口都代表了类的静态部分以及构造函数。
这两者(Set
和SetConstructor
)一起代表具有原生实现的Set
类。
Set
接口描述了实例,SetConstructor
表示类。
不同的构造方法(在SetConstructor
中描述)返回Set
,所以当你没有实例化Set
接口时,你会得到它的一个实例。
所有原生类型都已成为环境的一部分,无需导入string
,Set
,Map
,Promise
等。
通过声明它们(使用declare
关键字),您告诉编译器变量在运行时存在。
(3) 您需要区分值和类型 例如:
type MyPoint = {
x: number;
y: number;
}
const MyPoint: MyPoint = {
x: 0,
y: 0
}
这里MyPoint
既是一个类型(接口)又是一个值(const变量),它们都有相同的名称,两者之间没有冲突,因为你从不使用名称作为变量和一种类型
请注意,例如,类都是类型和值,因此您无法重用类名。
它没有“组合”这两个界面,会发生什么:
有一个名为Set
的变量,其类型为SetConstructor
在创建新实例(new Set()
)时,您正在调用此Set
变量中的一个方法,返回值的类型为Set
(接口)。
希望这能解决这个问题。
您应该将Set
变量视为:
const MyClass = class {
constructor(public x: string) {}
}
在这种情况下Set
接口是:
interface MyClass {
x: string;
}
SetConstructor
:
interface MyClassConstructor {
new (str: string): MyClass;
readonly prototype: MyClass;
}
唯一的区别是Set
的实现是原生的。