Looking at this as an example:
interface DOMPoint extends DOMPointReadOnly {
w: number;
x: number;
y: number;
z: number;
}
declare var DOMPoint: {
prototype: DOMPoint;
new(x?: number, y?: number, z?: number, w?: number): DOMPoint;
fromPoint(other?: DOMPointInit): DOMPoint;
};
interface DOMPointReadOnly {
readonly w: number;
readonly x: number;
readonly y: number;
readonly z: number;
matrixTransform(matrix?: DOMMatrixInit): DOMPoint;
toJSON(): any;
}
declare var DOMPointReadOnly: {
prototype: DOMPointReadOnly;
new(x?: number, y?: number, z?: number, w?: number): DOMPointReadOnly;
fromPoint(other?: DOMPointInit): DOMPointReadOnly;
};
interface DOMQuad {
readonly p1: DOMPoint;
readonly p2: DOMPoint;
readonly p3: DOMPoint;
readonly p4: DOMPoint;
getBounds(): DOMRect;
toJSON(): any;
}
Why are they declaring an uppercase variable the same name as the interface, with a different structure? What does it mean? And in the DOMQuad
when they reference DOMPoint
, are they referencing the var
or the interface
? What is the purpose of the var?
CodePudding user response:
It's providing type information for the built-in DOMPoint
class provided by the browser.
Why are they declaring an uppercase variable the same name as the interface, with a different structure?
The interface defines what instances of DOMPoint
look like. The declare global var DOMPoint
tells TypeScript that a global exists (provided by the browser) that is a function that creates DOMPoint
instances (new
) and a fromPoint
static method.
This mimics what TypeScript does with class X { }
, where it both creates a type (X
) for what instances of X
will look like, and a constructor function (X
) which is a runtime value (not just a type).
And in the
DOMQuad
when they referenceDOMPoint
, are they referencing the var or the interface?
The interface.
What is the purpose of the var?
Purely to tell TypeScript it exists. It doesn't create it (the browser does), it's just so TypeScript knows that using DOMPoint
is valid, it's a global that exists with the given signature.
CodePudding user response:
Types and values can have identical names. They aren't necessarily connected.
type A = string
const A = 123
const test: A = A // Type 'number' is not assignable to type 'string'.(2322)
One case where this comes into play often is classes.
class A {
static fromX(x: number) {
const instance = new A()
instance.x = x
return instance
}
x: number
}
In that snippet, an interface named A
is implicitly created that defines the type of instances of the A
class. But the value A
is that of the class constructor, which has a totally different interface.
For instance:
const obj: A = { x: 123 } // fine
Here obj
has all the properties that an instance of A
would have, so it's the correct type and all is well. The static method fromX
isn't on type A
because it's not on the instances of A
, it's on the constructor.
In fact, you can see the constructor has a very different type:
type AConstructor = typeof A
type fromXStaticMethod = AConstructor['fromX']
// type fromXStaticMethod = (x: number) => A
So that's more or less what's being modeled here.
interface DOMPoint extends DOMPointReadOnly {
w: number;
x: number;
y: number;
z: number;
}
declare var DOMPoint: {
prototype: DOMPoint;
new(x?: number, y?: number, z?: number, w?: number): DOMPoint;
fromPoint(other?: DOMPointInit): DOMPoint;
};
Here the interface DOMPoint
is the type of instances, and the value DOMPoint
is the constructor. So you can, for example, call DOMPoint.fromPoint()
and get an instance of DOMPoint
that has w,x,y,z properties.
interface DOMQuad {
readonly p1: DOMPoint;
readonly p2: DOMPoint;
readonly p3: DOMPoint;
readonly p4: DOMPoint;
getBounds(): DOMRect;
toJSON(): any;
}
Here a DOMQuad
instance has four points, and each point is a prop that is a DOMPoint
instance.