Como iniciar uma nova classe TS
dessa maneira (exemplo C#
para mostrar o que eu quero):
// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ... some code after
[edit]
Quando eu estava escrevendo esta pergunta, eu era desenvolvedor .NET puro, sem muito conhecimento de JS. Além disso, o TypeScript era algo completamente novo, anunciado como um novo superconjunto de JavaScript baseado em C #. Hoje vejo como essa pergunta foi estúpida.
De qualquer forma, se alguém ainda estiver procurando por uma resposta, observe as possíveis soluções abaixo.
A primeira coisa a observar é que no TS não devemos criar classes vazias para modelos. A melhor maneira é criar interface ou tipo (dependendo das necessidades). Bom artigo de Todd Motto: https://ultimatecourses.com/blog/classes-vs-interfaces-in-typescript
SOLUÇÃO 1:
type MyType = { prop1: string, prop2: string };
return <MyType> { prop1: '', prop2: '' };
SOLUÇÃO 2:
type MyType = { prop1: string, prop2: string };
return { prop1: '', prop2: '' } as MyType;
SOLUÇÃO 3 (quando você realmente precisa de uma aula):
class MyClass {
constructor(public data: { prop1: string, prop2: string }) {}
}
// ...
return new MyClass({ prop1: '', prop2: '' });
ou
class MyClass {
constructor(public prop1: string, public prop2: string) {}
}
// ...
return new MyClass('', '');
Obviamente, nos dois casos, você pode não precisar de tipos de conversão manualmente, porque eles serão resolvidos a partir do tipo de retorno de função / método.
fonte
return new MyClass { Field1: "ASD", Field2: "QWE" };
Respostas:
Atualizar
Desde que escrevemos esta resposta, surgiram maneiras melhores. Por favor, veja as outras respostas abaixo que têm mais votos e uma resposta melhor. Não consigo remover esta resposta, pois está marcada como aceita.
Resposta antiga
Há um problema no codeplex do TypeScript que descreve isso: Suporte para inicializadores de objetos .
Como afirmado, você já pode fazer isso usando interfaces no TypeScript em vez de classes:
fonte
Person
, mas não é uma instância dePerson
. Imagine que,Person
na verdade, seria uma classe com um construtor complexo e um monte de métodos, essa abordagem seria totalmente irrelevante. É bom que muitas pessoas achem sua abordagem útil, mas não é uma solução para a questão, como foi afirmado, e você poderia usar uma classe Person no seu exemplo, em vez de uma interface, seria do mesmo tipo.Atualizado em 12/07/2016: o Typecript 2.1 apresenta os tipos mapeados e fornece
Partial<T>
, o que permite fazer isso ....Resposta original:
Minha abordagem é definir uma
fields
variável separada que você passa para o construtor. O truque é redefinir todos os campos de classe para este inicializador como opcional. Quando o objeto é criado (com seus padrões), você simplesmente atribui o objeto inicializadorthis
;ou faça manualmente (um pouco mais seguro):
uso:
e saída do console:
Isso fornece segurança básica e inicialização de propriedade, mas tudo é opcional e pode estar com defeito. Você fica com os padrões da classe em paz se não passa um campo.
Você também pode misturá-lo com os parâmetros de construtor necessários - fique
fields
no final.Eu acho que o mais próximo do estilo C # ( a sintaxe real de init de campo foi rejeitada ). Eu preferiria o inicializador de campo adequado, mas não parece que isso ainda aconteça.
Para comparação, se você usar a abordagem de conversão, seu objeto inicializador deverá ter TODOS os campos para o tipo para o qual você está convertendo, além de não obter nenhuma função específica da classe (ou derivação) criada pela própria classe.
fonte
Partial<>
, apenasPerson
- isso exigirá que você passe um objeto que possui os campos obrigatórios. dito isso, consulte aqui as idéias (consulte Seleção) que limitam o mapeamento de tipos a determinados campos.public constructor(init?:Partial<Person>) { Object.assign(this, init); }
Abaixo está uma solução que combina uma aplicação mais curta
Object.assign
para modelar mais de perto oC#
padrão original .Mas primeiro, vamos revisar as técnicas oferecidas até o momento, que incluem:
Object.assign
Partial<T>
truque inteligente dentro do construtor de cópiasObject.create
vez deObject.assign
Obviamente, cada um tem seus prós / contras. Modificar uma classe de destino para criar um construtor de cópias nem sempre pode ser uma opção. E "vazamento" perde todas as funções associadas ao tipo de destino.
Object.create
parece menos atraente, pois requer um mapa descritor de propriedades bastante detalhado.Resposta mais curta, de uso geral
Portanto, aqui está outra abordagem que é um pouco mais simples, mantém a definição de tipo e os protótipos de funções associadas e modela mais de perto o
C#
padrão pretendido :É isso aí. A única adição sobre o
C#
padrão éObject.assign
juntamente com 2 parênteses e vírgula. Confira o exemplo de trabalho abaixo para confirmar que mantém os protótipos de função do tipo. Não são necessários construtores nem truques inteligentes.Exemplo de trabalho
Este exemplo mostra como inicializar um objeto usando uma aproximação de um
C#
inicializador de campo:fonte
Você pode afetar um objeto anônimo convertido no seu tipo de classe. Bônus : No visual studio, você se beneficia do intellisense dessa maneira :)
Editar:
AVISO Se a classe tiver métodos, a instância da sua classe não os obterá. Se o AClass tiver um construtor, ele não será executado. Se você usar instanceof AClass, ficará falso.
Em conclusão, você deve usar a interface e não a classe . O uso mais comum é para o modelo de domínio declarado como Objetos Antigos Simples. De fato, para o modelo de domínio, você deve usar melhor a interface em vez da classe. As interfaces são usadas no momento da compilação para verificação de tipo e, diferentemente das classes, as interfaces são completamente removidas durante a compilação.
fonte
AClass
contivesse métodos,anInstance
não os obteria.anInstance instanceof AClass
você obteráfalse
em tempo de execução.Sugiro uma abordagem que não requer o Typecript 2.1:
pontos chave:
Partial<T>
não obrigatóriofonte
new Person(<Person>{});
(porque a transmissão) e para ser claro também; usar Parcial <T> suporta funções. Por fim, se você tiver campos obrigatórios (mais funções de protótipo), precisará fazer:init: { name: string, address?: string, age: number }
e largar o elenco.class
entãovar
, se eu fizervar dog: {name: string} = {name: 'will be assigned later'};
, ele compila e obras. Alguma deficiência ou problema? Oh,dog
tem escopo muito pequeno e específico, significando apenas uma instância.Eu estaria mais inclinado a fazê-lo dessa maneira, usando (opcionalmente) propriedades e padrões automáticos. Você não sugeriu que os dois campos façam parte de uma estrutura de dados, por isso escolhi esse caminho.
Você pode ter as propriedades da classe e atribuí-las da maneira usual. E, obviamente, eles podem ou não ser necessários, então isso também é outra coisa. É que esse açúcar sintático é tão bom.
fonte
Em alguns cenários, pode ser aceitável usar
Object.create
. A referência do Mozilla inclui um polyfill se você precisar de retrocompatibilidade ou desejar rolar sua própria função de inicializador.Aplicado ao seu exemplo:
Cenários úteis
No meu caso, achei isso útil em testes de unidade por dois motivos:
__proto__
) e falhar no teste. Por exemplo:A saída da falha no teste de unidade não dará uma pista sobre o que é incompatível.
Por fim, a solução proposta em http://typescript.codeplex.com/workitem/334 não suporta declaração embutida no estilo json. Por exemplo, o seguinte não é compilado:
fonte
Eu queria uma solução que tivesse o seguinte:
Aqui está a maneira que eu faço:
Todas as propriedades no construtor são obrigatórias e não podem ser omitidas sem um erro do compilador.
É dependente do
OnlyData
que filtragetFullName()
as propriedades necessárias e é definido da seguinte maneira:Limitações atuais dessa maneira:
fonte
Esta é outra solução:
fonte
Você pode ter uma classe com campos opcionais (marcados com?) E um construtor que recebe uma instância da mesma classe.
Nesse caso, você não poderá omitir os campos obrigatórios. Isso fornece controle refinado sobre a construção do objeto.
Você pode usar o construtor com o tipo Parcial, conforme observado em outras respostas:
O problema é que todos os campos se tornam opcionais e isso não é desejável na maioria dos casos.
fonte
A maneira mais fácil de fazer isso é com a conversão de tipo.
fonte
MyClass
?Se você estiver usando uma versão antiga do texto datilografado <2.1, poderá usar semelhante ao seguinte, que é basicamente o lançamento de qualquer objeto digitado:
fonte
se você deseja criar uma nova instância sem definir o valor inicial quando a instância
1- você tem que usar a classe não interface
2- você precisa definir o valor inicial ao criar a classe
fonte