La creación de objetos es parte del ciclo de desarrollo de software. Siempre los estamos creando, los objetos a construir pueden tener diferentes significados, así podemos tener objetos tipo POCO, DTO, Value Object, etc.

Dado que estamos en typescript, para la creación del objeto haremos que cumpla una determinada interfaz. Por ejemplo, partimos de una interfaz «IInvoice«.

interface IInvoice {
    invoiceDate: Date;
    invoiceNumber: string;
    totalAmount: number;
}

Podemos construir un objeto que cumpla esa interfaz de dos maneras distintas

Tipos de construcción

Varias maneras de crear un objeto

Objeto literal

Simplemente basta con declarar el objeto y sus propiedades con su valor de la siguiente manera:

const invoiceLiteral: IInvoice = {
    invoiceDate: new Date(),
    invoiceNumber: '',
    totalAmount: 0
}

Ahora podemos usar el objeto “invoiceLiteral”. La creación del objeto se inicializa con los valores asignados en esa construcción, con lo que directamente podemos poner unos valores específicos.

Objeto construido

Mediante la palabra reservada “new” nos permitirá crear un objeto a partir de una clase.

class Invoice implements IInvoice {
    invoiceDate: Date = new Date();
    invoiceNumber: string = '';
    totalAmount: number =  0;
}

const invoiceObjectDefault: IInvoice = new Invoice();

En este caso no hemos especificado ningún constructor, con lo que la clase (aunque no se vea) tiene su constructor por defecto. De esa manera al hacer el new construye el objeto con los valores por defecto asignados.

Si a posteriori queremos cambiar los valores, deberemos acceder a su propiedad y asignar el nuevo valor:

invoiceObjectDefault.invoiceNumber = '123';
invoiceObjectDefault.totalAmount = 23;

En el caso que se desee inicializar con unos valores determinados, se puede crear un constructor como el siguiente:

class Invoice implements IInvoice {
    invoiceDate: Date = new Date();
    invoiceNumber: string = '';
    totalAmount: number =  0;
 
    constructor(invoiceDate: Date, invoiceNumber: string,  totalAmount: number) {
        this.invoiceDate = invoiceDate;
        this.invoiceNumber = invoiceNumber;
        this.totalAmount = totalAmount;
    }
}
 
const invoiceObject: IInvoice = new Invoice(new Date(), '', 0);

El acceso y modificación de los valores se realiza como cualquier otro objeto:

invoiceObject.invoiceNumber = '123';
invoiceObject.totalAmount = 23;

Temas interesantes

Type Assertion

En la construcción podemos crear un objeto de un tipo en concreto sin declarar todas las propiedades en la construcción (en nuestro caso que siga la interfaz) jugando con el type assertion, que es decirle al compilador que confíe en lo que estamos haciendo y que el objeto que creamos es correcto.

Así podemos crear un objeto de tipo «IInvoice» sin inicializar ninguna propiedad (sin cumplir la interfaz). Inicialmente daría un error si lo hacemos de la siguiente manera:

const invoice: IInvoice = {};

Lo único que hay que añadir es esa parte de “confía en mí, es un objeto tipo IInvoice” mediante la palabra reservada “as”, quedando finalmente:

const invoice: IInvoice = {} as IInvoice;

Ya no daría error, PERO si accedemos a cualquiera de sus propiedades daría como resultado “undefined” puesto que cualquiera de sus propiedades no las hemos seteado. Puede ser fuente de bugs y hay que tener mucho cuidado.

Conclusiones

No hay una única manera de realizar la creación de objetos, aunque se recomienda usar la construcción mediante “object literal” en vez del «new» por rendimiento.

A partir de aquí, se pueden implementar los diferentes patrones de diseño referentes a la construcción como pueden ser el Singleton, Builder, etc.