¿Solo quiero declarar una propiedad estática en la interfaz mecanografiada ? No he encontrado nada al respecto.
interface myInterface {
static Name:string;
}
¿Es posible?
¿Solo quiero declarar una propiedad estática en la interfaz mecanografiada ? No he encontrado nada al respecto.
interface myInterface {
static Name:string;
}
¿Es posible?
Respuestas:
No puede definir una propiedad estática en una interfaz en TypeScript.
Supongamos que desea cambiar el Dateobjeto, en lugar de intentar agregar a las definiciones de Date, puede envolverlo o simplemente crear su clase de fecha enriquecida para hacer las cosas que Dateno funcionan.
class RichDate {
public static MinValue = new Date();
}
Debido a que Date es una interfaz en TypeScript, no puedes extenderla con una clase usando la extendspalabra clave, lo cual es un poco vergonzoso, ya que sería una buena solución si date fuera una clase.
Si desea extender el objeto Date para proporcionar una MinValuepropiedad en el prototipo, puede:
interface Date {
MinValue: Date;
}
Date.prototype.MinValue = new Date(0);
Llamado usando:
var x = new Date();
console.log(x.MinValue);
Y si quieres que esté disponible sin una instancia, también puedes ... pero es un poco complicado.
interface DateStatic extends Date {
MinValue: Date;
}
Date['MinValue'] = new Date(0);
Llamado usando:
var x: DateStatic = <any>Date; // We aren't using an instance
console.log(x.MinValue);
extendspalabra clave. Simplemente no puede extender una interfaz con una clase (lo que tendría que hacer para agregar una propiedad estática).
Siga la respuesta de @Bartvds de @ Duncan, aquí para proporcionar una forma viable después de que pasaron los años.
En este punto, después del lanzamiento de Typescript 1.5 (@Jun 15 '15), su interfaz útil
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
se puede implementar de esta manera con la ayuda del decorador.
/* class decorator */
function staticImplements<T>() {
return <U extends T>(constructor: U) => {constructor};
}
@staticImplements<MyTypeStatic>() /* this statement implements both normal interface & static interface */
class MyTypeClass { /* implements MyType { */ /* so this become optional not required */
public static staticMethod() {}
instanceMethod() {}
}
Consulte mi comentario en github open issue 13462 .
resultado visual: error de compilación con un indicio de falta de método estático.

Después de implementar el método estático, se indica que falta el método.

La compilación pasó después de que se cumplieron tanto la interfaz estática como la interfaz normal.

Puede definir la interfaz normalmente:
interface MyInterface {
Name:string;
}
pero no puedes simplemente hacer
class MyClass implements MyInterface {
static Name:string; // typescript won't care about this field
Name:string; // and demand this one instead
}
Para expresar que una clase debe seguir esta interfaz por sus propiedades estáticas, necesita un poco de engaño:
var MyClass: MyInterface;
MyClass = class {
static Name:string; // if the class doesn't have that field it won't compile
}
Incluso puede mantener el nombre de la clase, a TypeScript (2.0) no le importará:
var MyClass: MyInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that field it won't compile
}
Si desea heredar de muchas interfaces de forma estática, primero deberá fusionarlas en una nueva:
interface NameInterface {
Name:string;
}
interface AddressInterface {
Address:string;
}
interface NameAndAddressInterface extends NameInterface, AddressInterface { }
var MyClass: NameAndAddressInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that static field code won't compile
static Address:string; // if the class doesn't have that static field code won't compile
}
O si no desea nombrar la interfaz fusionada, puede hacer:
interface NameInterface {
Name:string;
}
interface AddressInterface {
Address:string;
}
var MyClass: NameInterface & AddressInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that static field code won't compile
static Address:string; // if the class doesn't have that static field code won't compile
}
Ejemplo de trabajo
@staticImplements.
reply(msg: IBotMsg): Promise<IBotReply>
Las propiedades estáticas generalmente se colocan en el constructor (global) del objeto, mientras que la palabra clave "interfaz" se aplica a las instancias del objeto.
La respuesta anterior dada es, por supuesto, correcta si está escribiendo la clase en TypeScript. Puede ayudar a otros saber que si está describiendo un objeto que ya está implementado en otro lugar, entonces el constructor global, incluidas las propiedades estáticas, se puede declarar así:
declare var myInterface : {
new(): Interface;
Name:string;
}
Los modificadores estáticos no pueden aparecer en un miembro de tipo (error de TypeScript TS1070). Por eso recomiendo usar una clase abstracta para resolver la misión:
Ejemplo
// Interface definition
abstract class MyInterface {
static MyName: string;
abstract getText(): string;
}
// Interface implementation
class MyClass extends MyInterface {
static MyName = 'TestName';
getText(): string {
return `This is my name static name "${MyClass.MyName}".`;
}
}
// Test run
const test: MyInterface = new MyClass();
console.log(test.getText());
La solución de @ duncan anterior que especifica new()el tipo estático también funciona con interfaces:
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
implement?
MyType(como en class Foo implements MyType). La interfaz estática solo es realmente útil en las definiciones, cuando se describe el código JS existente.
Si está buscando definir una clase estática (es decir, todos los métodos / propiedades son estáticos), puede hacer algo como esto:
interface MyStaticClassInterface {
foo():string;
}
var myStaticClass:MyStaticClassInterface = {
foo() {
return 'bar';
}
};
En este caso, la "clase" estática es en realidad un objeto simple-ol'-js, que implementa todos los métodos de MyStaticClassInterface
Sí, es posible. Aqui esta la solucion
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
Foode nombres para reemplazar una definición de clase? donde Class Foo implementaría statMethod (), esto parece un truco, especialmente porque los espacios de nombres están en desuso ahora ...
waiting more feedback. Por lo tanto, espere hasta que se agreguen métodos estáticos a la interfaz o hágalo de esta manera.
export namespacees realmente la implementación de tu clase? Eso parece estar doblando mucho las cosas. Me pregunto qué más se rompe en las clases.
Otra opción que no se menciona aquí es definir la variable con un tipo que representa la interfaz estática y asignarle una expresión de clase:
interface MyType {
instanceMethod(): void;
}
interface MyTypeStatic {
new(): MyType;
staticMethod(): void;
}
// ok
const MyTypeClass: MyTypeStatic = class MyTypeClass {
public static staticMethod() { }
instanceMethod() { }
}
// error: 'instanceMethod' is missing
const MyTypeClass1: MyTypeStatic = class MyTypeClass {
public static staticMethod() { }
}
// error: 'staticMethod' is missing
const MyTypeClass2: MyTypeStatic = class MyTypeClass {
instanceMethod() { }
}
El efecto es el mismo que en la respuesta con decoradores , pero sin gastos generales de decoradores.
Sugerencia / discusión relevante en GitHub
Puede fusionar la interfaz con el espacio de nombres usando el mismo nombre:
interface myInterface { }
namespace myInterface {
Name:string;
}
Pero esta interfaz solo es útil para saber que tiene propiedad Name. No puedes implementarlo.
Encontré una manera de hacer esto (sin decoradores) para mi caso de uso específico.
La parte importante que verifica los miembros estáticos es IObjectClassy usar cls: IObjectClass<T>en el createObjectmétodo:
//------------------------
// Library
//------------------------
interface IObject {
id: number;
}
interface IObjectClass<T> {
new(): T;
table_name: string;
}
function createObject<T extends IObject>(cls: IObjectClass<T>, data:Partial<T>):T {
let obj:T = (<any>Object).assign({},
data,
{
id: 1,
table_name: cls.table_name,
}
)
return obj;
}
//------------------------
// Implementation
//------------------------
export class User implements IObject {
static table_name: string = 'user';
id: number;
name: string;
}
//------------------------
// Application
//------------------------
let user = createObject(User, {name: 'Jimmy'});
console.log(user.name);
Aunque la palabra clave estática no es compatible con la interfaz de TypeScript, podemos lograrlo creando un function interfacemiembro que tenga estático.
En mi siguiente código, he creado una interfaz de función Factoryque tiene dos miembros estáticos serialNumbery printSerial .
// factory is a function interface
interface Factory<T> {
(name: string, age: number): T;
//staic property
serialNumber: number;
//static method
printSrial: () => void;
}
class Dog {
constructor(public name: string, public age: number) { }
}
const dogFactory: Factory<Dog> = (name, age) => {
return new Dog(name, age);
}
// initialising static members
dogFactory.serialNumber = 1234;
dogFactory.printSrial = () => console.log(dogFactory.serialNumber);
//instance of Dog that DogFactory creates
const myDog = dogFactory("spike", 3);
//static property that returns 1234
console.log(dogFactory.serialNumber)
//static method that prints the serial 1234
dogFactory.printSrial();
Implementé una solución como la de Kamil Szot y tiene un efecto no deseado. No tengo suficiente reputación para publicar esto como comentario, así que lo publico aquí en caso de que alguien intente esa solución y lea esto.
La solucion es:
interface MyInterface {
Name: string;
}
const MyClass = class {
static Name: string;
};
Sin embargo, usar una expresión de clase no me permite usar MyClasscomo tipo. Si escribo algo como:
const myInstance: MyClass;
myInstanceresulta ser de tipo any, y mi editor muestra el siguiente error:
'MyClass' refers to a value, but is being used as a type here. Did you mean 'typeof MyClass'?ts(2749)
Termino perdiendo una escritura más importante que la que quería lograr con la interfaz para la parte estática de la clase.
La solución de Val usando un decorador evita este error.