Eu só quero declarar uma propriedade estática na interface typescript ? Eu não encontrei nada sobre isso.
interface myInterface {
static Name:string;
}
É possível?
Eu só quero declarar uma propriedade estática na interface typescript ? Eu não encontrei nada sobre isso.
interface myInterface {
static Name:string;
}
É possível?
Respostas:
Você não pode definir uma propriedade estática em uma interface em TypeScript.
Digamos que você queira alterar o Dateobjeto, em vez de tentar adicionar às definições de Date, você pode embrulhá-lo ou simplesmente criar sua classe de data rica para fazer o que Datenão faz.
class RichDate {
public static MinValue = new Date();
}
Como Date é uma interface em TypeScript, você não pode estendê-la com uma classe usando a extendspalavra - chave, o que é uma pena, pois seria uma boa solução se date fosse uma classe.
Se você deseja estender o objeto Date para fornecer uma MinValuepropriedade no protótipo, você pode:
interface Date {
MinValue: Date;
}
Date.prototype.MinValue = new Date(0);
Chamado usando:
var x = new Date();
console.log(x.MinValue);
E se você quiser torná-lo disponível sem uma instância, você também pode ... mas é um pouco complicado.
interface DateStatic extends Date {
MinValue: Date;
}
Date['MinValue'] = new Date(0);
Chamado usando:
var x: DateStatic = <any>Date; // We aren't using an instance
console.log(x.MinValue);
extendspalavra - chave. Você simplesmente não pode estender uma interface com uma classe (o que você precisaria fazer para adicionar uma propriedade estática).
Siga a resposta de @Duncan's @ Bartvds, aqui para fornecer uma maneira viável depois que anos se passaram.
Neste ponto, após o lançamento do Typescript 1.5 (@Jun 15 '15), sua interface útil
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
pode ser implementado desta forma com a ajuda do 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 meu comentário no github open issue 13462 .
resultado visual: erro de compilação com uma dica de método estático ausente.

Após a implementação do método estático, falta a dica para o método.

A compilação passou depois que a interface estática e a interface normal foram cumpridas.

Você pode definir a interface normalmente:
interface MyInterface {
Name:string;
}
mas você não pode simplesmente fazer
class MyClass implements MyInterface {
static Name:string; // typescript won't care about this field
Name:string; // and demand this one instead
}
Para expressar que uma classe deve seguir esta interface para suas propriedades estáticas, você precisa de alguns truques:
var MyClass: MyInterface;
MyClass = class {
static Name:string; // if the class doesn't have that field it won't compile
}
Você pode até manter o nome da classe, o TypeScript (2.0) não se importará:
var MyClass: MyInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that field it won't compile
}
Se você deseja herdar de muitas interfaces estaticamente, você terá que fundi-las primeiro em uma nova:
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
}
Ou, se não quiser nomear a interface mesclada, você pode fazer:
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
}
Exemplo de trabalho
@staticImplements.
reply(msg: IBotMsg): Promise<IBotReply>
As propriedades estáticas geralmente são colocadas no construtor (global) do objeto, enquanto a palavra-chave "interface" se aplica a instâncias do objeto.
A resposta anterior fornecida é obviamente correta se você estiver escrevendo a classe em TypeScript. Pode ser útil saber que se você está descrevendo um objeto que já está implementado em outro lugar, o construtor global incluindo propriedades estáticas pode ser declarado assim:
declare var myInterface : {
new(): Interface;
Name:string;
}
Os modificadores estáticos não podem aparecer em um membro de tipo (erro do TypeScript TS1070). É por isso que recomendo usar uma classe abstrata para resolver a missão:
Exemplo
// 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());
A solução de @duncan acima especificando new()para o tipo estático também funciona com interfaces:
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
implement?
MyType(como em class Foo implements MyType). A interface estática só é realmente útil em definições, ao descrever o código JS existente.
Se você estiver procurando definir uma classe estática (ou seja, todos os métodos / propriedades são estáticos), você pode fazer algo assim:
interface MyStaticClassInterface {
foo():string;
}
var myStaticClass:MyStaticClassInterface = {
foo() {
return 'bar';
}
};
Neste caso, a "classe" estática é realmente apenas um objeto-js simples, que implementa todos os métodos de MyStaticClassInterface
Sim, é possível. Aqui está a solução
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
Foopara substituir uma definição de classe? onde a classe Foo implementaria o statMethod () isso parece um pouco um hack, especialmente porque os namespaces estão meio que obsoletos agora ...
waiting more feedback. Portanto, você pode esperar até que métodos estáticos sejam adicionados à interface ou fazer desta forma.
export namespaceé realmente a implementação de sua classe? Isso parece estar distorcendo muito as coisas. Eu me pergunto o que mais isso quebra nas aulas?
Outra opção não mencionada aqui é definir a variável com um tipo que representa a interface estática e atribuir a ela uma expressão de classe:
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() { }
}
O efeito é o mesmo que na resposta com decoradores , mas sem sobrecarga de decoradores
Sugestão / discussão relevante no GitHub
Você pode mesclar interface com namespace usando o mesmo nome:
interface myInterface { }
namespace myInterface {
Name:string;
}
Mas essa interface só é útil para saber se ela possui propriedades Name. Você não pode implementá-lo.
Eu encontrei uma maneira de fazer isso (sem decoradores) para meu caso de uso específico.
A parte importante que verifica se há membros estáticos é IObjectClasse usando cls: IObjectClass<T>no 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);
Embora a palavra-chave estática não seja suportada na interface em Typescript, podemos alcançá-la criando um function interface que tenha um membro estático.
Em meu código a seguir, criei uma interface de função Factoryque tem dois membros estáticos serialNumbere 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();
Eu implementei uma solução como a de Kamil Szot e teve um efeito indesejado. Eu não tenho reputação suficiente para postar isso como um comentário, então eu posto aqui caso alguém esteja tentando essa solução e leia isso.
A solução é:
interface MyInterface {
Name: string;
}
const MyClass = class {
static Name: string;
};
No entanto, usar uma expressão de classe não me permite usar MyClasscomo um tipo. Se eu escrever algo como:
const myInstance: MyClass;
myInstanceacabou sendo do tipo any, e meu editor mostra o seguinte erro:
'MyClass' refers to a value, but is being used as a type here. Did you mean 'typeof MyClass'?ts(2749)
Acabo perdendo uma digitação mais importante do que a que eu queria conseguir com a interface para a parte estática da aula.
A solução de Val usando um decorador evita essa armadilha.