Como usar namespaces em TypeScript
Evitar conflitos de nomenclatura pode ser complicado e levar a códigos complicados, mas os namespaces oferecem uma solução conveniente.
Uma colisão de nomenclatura ocorre quando dois ou mais componentes de código usam o mesmo nome para uma variável, função ou classe. Eles são comuns em grandes projetos onde muitas pessoas trabalham na mesma base de código. Eles podem dificultar a determinação de qual componente do código é responsável pelos bugs.
Usando namespaces, você pode organizar e gerenciar seu código para que grupos de componentes relacionados fiquem sob um identificador comum. Isso reduzirá o risco de conflitos de nomenclatura.
Criando um Namespace
Você pode criar namespaces em TypeScript usando a palavra-chave namespace. Siga-o com um identificador para nomear o namespace e um bloco entre chaves. A sintaxe é semelhante àquela que você usaria para criar uma classe em JavaScript.
Por exemplo:
namespace Example {}
Você pode então declarar membros do namespace — variáveis, funções e classes — dentro do bloco de namespace:
namespace Example {
export function Foo(): void {
console.log("This is a function inside the Example namespace");
}
export class Bar {
property: string;
constructor(property: string) {
this.property = property;
}
}
export const baz = "This is a namespace variable"
}
No exemplo acima, Foo, < forte>Barra e baz são membros do Exemplo espaço para nome. Por padrão, você só pode acessar os membros de um namespace dentro desse mesmo namespace. Use a palavra-chave export para tornar cada membro do namespace acessível fora dele.
Você pode acessar todos os membros publicamente disponíveis de um namespace chamando o nome do membro do namespace usando a notação de ponto:
Example.foo(); // This is a function inside the Example namespace
const bar = new Example.Bar("string");
console.log(bar.property); // string
console.log(Example.baz); // This is a namespace variable
Aninhando Namespaces
TypeScript permite aninhar namespaces dentro de outros namespaces para criar uma estrutura hierárquica para seu código. O aninhamento de namespaces pode reduzir ainda mais os riscos de colisões de nomes, agrupando namespaces relacionados sob um identificador comum.
Por exemplo:
namespace Example {
export const property_1 = "Foo";
export namespace Bar {
export const printFoo = function () {
console.log(property_1);
};
}
export namespace Baz {
export class Foo {
property: string;
constructor(property: string) {
this.property = property;
}
}
}
}
O bloco de código acima fornece um exemplo de namespace aninhado. O Exemplo namespace é o namespace de nível superior, contendo o namespace Bar e o namespace Namespace Baz.
Você pode acessar as propriedades em um namespace aninhado usando a notação de ponto que segue a estrutura hierárquica que você criou.
Por exemplo:
console.log(Example.property_1); // Foo
Example.Bar.printFoo() // Foo
const foo = new Example.Baz.Foo("example")
Este código de exemplo acessa cada membro do namespace por meio do namespace pai. Acessar uma propriedade diretamente, em vez de por meio de seu namespace pai, geraria um erro:
Example.printFoo()
// error TS2339: Property 'printFoo' does not exist on type 'typeof Example'
Embora o aninhamento de namespaces possa ajudá-lo a organizar seu código, namespaces profundamente aninhados podem produzir o efeito oposto. Namespaces profundamente aninhados tornam seu código mais difícil de ler e manter.
Aliases de namespace
Um alias de namespace é um nome abreviado dado a um membro do namespace, o que facilita a referência.
Você pode criar um alias de namespace usando importação palavra-chave seguida do nome que você deseja atribuir ao alias. Em seguida, atribua a palavra-chave import e o nome alternativo a um membro do namespace.
Por exemplo:
namespace Car {
export namespace Tesla {
export class ModelX {
create(): String {
return `Model X Created`
}
}
}
export namespace Toyota {
export class Camry {}
}
export namespace Ford {
export class Mustang {}
}
}
// Creating the alias
import tesla = Car.Tesla
const modelX = new tesla.ModelX()
modelX.create() // Model X Created
Este exemplo cria um alias para o namespace Car.Tesla. Você pode usar esse alias para acessar propriedades do Tesla< namespace, como a classe ModelX, com mais facilidade.
Usando namespaces em vários arquivos
Para usar um namespace em um arquivo diferente, é necessário importá-lo. Importar namespaces é diferente de importar variáveis, funções, classes, etc. Dependendo do sistema de módulos do seu projeto, você pode importá-los usando o exigir ou < palavra-chave forte>importar.
No entanto, você só pode importar namespaces usando a diretiva de barra tripla, que é um comentário de linha única contendo uma tag XML.
Por exemplo:
// main.ts
/// <reference path="index.ts" />
Example.foo()
Este exemplo usa a diretiva de barra tripla dentro de um main.ts. A diretiva faz referência ao arquivo index.ts, que contém o namespace Example. Sem importação, o namespace só estará disponível no mesmo arquivo que o define.
Depois de referenciar o index.ts<, você pode acessar o exemplo namespace e seus membros disponíveis publicamente. Por exemplo, você pode chamar o método foo no Exemplo namespace.
Depois de usar vários arquivos, você precisará garantir que o TypeScript compile e carregue todo o código necessário. Você pode fazer isso concatenando a saída do compilador TypeScript usando a opção outFile. Isso compilará todos os arquivos de entrada em um único arquivo de saída JavaScript. A sintaxe geral para executar o compilador assim é:
tsc --outFile <JAVASCRIPT_FILE> <TYPESCRIPT_FILE>
Substitua
Por exemplo:
tsc --outFile index.js main.ts
Este comando irá compilar o conteúdo do main.ts, juntamente com todos os arquivos referenciados pela diretiva de barra tripla, no arquivo index.js arquivo.
Alternativamente, você pode especificar cada arquivo individualmente:
tsc --outFile <JAVASCRIPT_FILE> <TYPESCRIPT_FILE_1> <TYPESCRIPT_FILE_2>
É importante notar que a diretiva de barra tripla só é válida quando declarada no topo de um arquivo. Se você tentar usá-lo em qualquer outro lugar, o TypeScript o tratará como um comentário normal de linha única, sem nenhum significado especial.
Você deve usar namespaces ou módulos?
Embora os namespaces não estejam obsoletos, geralmente é recomendável organizar e gerenciar seu código usando módulos ES6. Os módulos são mais fáceis de manter e gerenciar e você pode ampliá-los em vários arquivos.
Além disso, você pode especificar os relacionamentos entre módulos em termos de importações e exportações no nível do arquivo. Namespaces não podem definir suas dependências.
Em última análise, a escolha entre namespaces e módulos dependerá das necessidades e requisitos específicos do seu projeto, pois ambos oferecem uma forma valiosa de organizar e gerenciar código em TypeScript.