Cómo iniciar una nueva clase de TS
tal manera (ejemplo C#
para mostrar lo que quiero):
// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ... some code after
[editar]
Cuando escribía esta pregunta, era un desarrollador puro de .NET sin mucho conocimiento de JS. También TypeScript era algo completamente nuevo, anunciado como un nuevo superconjunto de JavaScript basado en C #. Hoy veo cuán estúpida fue esta pregunta.
De todos modos, si alguien todavía está buscando una respuesta, consulte las posibles soluciones a continuación.
Lo primero a tener en cuenta es que en TS no deberíamos crear clases vacías para los modelos. La mejor manera es crear una interfaz o tipo (según las necesidades). Buen artículo de Todd Motto: https://ultimatecourses.com/blog/classes-vs-interfaces-in-typescript
SOLUCIÓN 1:
type MyType = { prop1: string, prop2: string };
return <MyType> { prop1: '', prop2: '' };
SOLUCIÓN 2:
type MyType = { prop1: string, prop2: string };
return { prop1: '', prop2: '' } as MyType;
SOLUCIÓN 3 (cuando realmente necesitas una clase):
class MyClass {
constructor(public data: { prop1: string, prop2: string }) {}
}
// ...
return new MyClass({ prop1: '', prop2: '' });
o
class MyClass {
constructor(public prop1: string, public prop2: string) {}
}
// ...
return new MyClass('', '');
Por supuesto, en ambos casos, es posible que no necesite tipos de conversión manualmente porque se resolverán a partir del tipo de retorno de función / método.
fuente
return new MyClass { Field1: "ASD", Field2: "QWE" };
Respuestas:
Actualizar
Desde que escribí esta respuesta, han surgido mejores formas. Vea las otras respuestas a continuación que tienen más votos y una mejor respuesta. No puedo eliminar esta respuesta ya que está marcada como aceptada.
Vieja respuesta
Hay un problema en el codeplex de TypeScript que describe esto: Soporte para inicializadores de objetos .
Como se indicó, ya puede hacerlo mediante el uso de interfaces en TypeScript en lugar de clases:
fuente
Person
, pero no es en absoluto una instancia dePerson
. Imagine que enPerson
realidad sería una clase con un constructor complejo y un montón de métodos, este enfoque caería de bruces. Es bueno que un grupo de personas encuentre útil su enfoque, pero no es una solución a la pregunta como se dice y podría usar una persona de clase en su ejemplo en lugar de una interfaz, sería del mismo tipo.Actualizado el 12/07/2016: Typecript 2.1 presenta Tipos mapeados y proporciona
Partial<T>
, lo que le permite hacer esto ...Respuesta original
Mi enfoque es definir una
fields
variable separada que pase al constructor. El truco consiste en redefinir todos los campos de clase para este inicializador como opcional. Cuando se crea el objeto (con sus valores predeterminados) simplemente asigna el objeto inicializadorthis
;o hacerlo manualmente (un poco más seguro):
uso:
y salida de consola:
Esto le brinda seguridad básica e inicialización de la propiedad, pero todo es opcional y puede estar fuera de servicio. Si no pasa un campo, obtiene los valores predeterminados de la clase solo.
También puede mezclarlo con los parámetros de constructor requeridos: pegue
fields
al final.Creo que lo más parecido al estilo C # que vas a conseguir ( se rechazó la sintaxis real field-init ). Prefiero el iniciador de campo apropiado, pero no parece que suceda todavía.
A modo de comparación, si utiliza el enfoque de conversión, su objeto de inicialización debe tener TODOS los campos para el tipo al que está enviando, además de no obtener ninguna función específica de clase (o derivaciones) creada por la clase misma.
fuente
Partial<>
, simplementePerson
, eso requerirá que pase un objeto que tenga los campos requeridos. Dicho esto, consulte aquí las ideas (ver Selección) que limitan la asignación de tipos a ciertos campos.public constructor(init?:Partial<Person>) { Object.assign(this, init); }
A continuación se muestra una solución que combina una aplicación más corta
Object.assign
para modelar más de cerca el original.C#
patrón .Pero primero, revisemos las técnicas ofrecidas hasta ahora, que incluyen:
Object.assign
Partial<T>
truco dentro del constructor de copiasObject.create
lugar deObject.assign
Por supuesto, cada uno tiene sus pros / contras. Modificar una clase de destino para crear un constructor de copia puede no ser siempre una opción. Y "casting" pierde las funciones asociadas con el tipo de destino.
Object.create
parece menos atractivo ya que requiere un mapa descriptor de propiedades bastante detallado.La respuesta más breve de uso general
Entonces, aquí hay otro enfoque que es algo más simple, mantiene la definición de tipo y los prototipos de funciones asociadas, y modela más de cerca el
C#
patrón deseado :Eso es. La única adición sobre el
C#
patrón esObject.assign
junto con 2 paréntesis y una coma. Consulte el siguiente ejemplo de trabajo para confirmar que mantiene los prototipos de función del tipo. No se requieren constructores, ni trucos ingeniosos.Ejemplo de trabajo
Este ejemplo muestra cómo inicializar un objeto usando una aproximación de un
C#
inicializador de campo:fuente
Puede afectar a un objeto anónimo lanzado en su tipo de clase. Bonificación : en Visual Studio, te beneficiarás de intellisense de esta manera :)
Editar:
ADVERTENCIA Si la clase tiene métodos, la instancia de su clase no los obtendrá. Si AClass tiene un constructor, no se ejecutará. Si utiliza instancia de AClass, obtendrá falso.
En conclusión, debe usar la interfaz y no la clase . El uso más común es para el modelo de dominio declarado como Objetos antiguos simples. De hecho, para el modelo de dominio, debería usar mejor la interfaz en lugar de la clase. Las interfaces se utilizan en el momento de la compilación para la verificación de tipos y, a diferencia de las clases, las interfaces se eliminan por completo durante la compilación.
fuente
AClass
contuviera métodos,anInstance
no los obtendría.anInstance instanceof AClass
, llegarásfalse
en tiempo de ejecución.Sugiero un enfoque que no requiere Typecript 2.1:
puntos clave:
Partial<T>
no requeridofuente
new Person(<Person>{});
(debido a la conversión) y también debe ser claro; El uso de <T> parcial admite funciones. En última instancia, si tiene campos obligatorios (más funciones de prototipo) deberá hacer lo siguiente:init: { name: string, address?: string, age: number }
y descartar el elenco.class
y luegovar
, si lo hagovar dog: {name: string} = {name: 'will be assigned later'};
, compila y funciona. ¿Alguna deficiencia o problema? Oh,dog
tiene un alcance muy pequeño y específico, lo que significa solo una instancia.Estaría más inclinado a hacerlo de esta manera, usando (opcionalmente) propiedades automáticas y valores predeterminados. No ha sugerido que los dos campos son parte de una estructura de datos, por eso elegí de esta manera.
Puede tener las propiedades en la clase y luego asignarlas de la manera habitual. Y, obviamente, pueden o no ser necesarios, por lo que también es otra cosa. Es solo que este es un azúcar sintáctico tan agradable.
fuente
En algunos escenarios, puede ser aceptable usar
Object.create
. La referencia de Mozilla incluye un polyfill si necesita compatibilidad con versiones anteriores o si desea implementar su propia función de inicializador.Aplicado a tu ejemplo:
Escenarios útiles
En mi caso, encontré esto útil en pruebas unitarias por dos razones:
__proto__
) y fallar la prueba. Por ejemplo:El resultado de la falla de la prueba de la unidad no dará una pista sobre lo que no coincide.
Finalmente, la solución propuesta en http://typescript.codeplex.com/workitem/334 no admite la declaración en línea de estilo json. Por ejemplo, lo siguiente no se compila:
fuente
Quería una solución que tuviera lo siguiente:
Aquí está la forma en que lo hago:
Todas las propiedades en el constructor son obligatorias y no pueden omitirse sin un error del compilador.
Depende de
OnlyData
que se filtre fueragetFullName()
de las propiedades requeridas y se define así:Limitaciones actuales de esta manera:
fuente
Esta es otra solución:
fuente
Podría tener una clase con campos opcionales (marcados con?) Y un constructor que recibe una instancia de la misma clase.
En este caso, no podrá omitir los campos obligatorios. Esto le brinda un control detallado sobre la construcción del objeto.
Puede usar el constructor con el tipo Parcial como se indica en otras respuestas:
El problema es que todos los campos se vuelven opcionales y no es deseable en la mayoría de los casos.
fuente
La forma más fácil de hacerlo es con el tipo de conversión.
fuente
MyClass
?Si está utilizando una versión anterior de mecanografiado <2.1, puede usar una similar a la siguiente, que básicamente es la conversión de cualquier objeto tipeado:
fuente
si desea crear una nueva instancia sin establecer el valor inicial cuando la instancia
1- tienes que usar clase no interfaz
2- tienes que establecer el valor inicial al crear la clase
fuente