No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Partial y Required Type

18/22
Recursos

Los tipos Partial y Required en TypeScript son utility types que te permiten crear un nuevo tipo basado en un tipo existente, pero haciendo que todas las propiedades de ese tipo sean opcionales u obligatorias.

Partial type en TypeScript

Utilizamos la siguiente expresión para definir un Partial type: Partial<T>. Esto genera un nuevo tipo que tiene todas las propiedades de T, pero cada atributo es opcional. Veamos un ejemplo:

interface User {
  id: number;
  name: string;
  email: string;
  phoneNumber: string;
}

// Usando `Partial` para hacer todas las propiedades de User opcionales
type PartialUser = Partial<User>;

// `PartialUser` es ahora un tipo con todas las propiedades de `User`, pero cada una de ellas es opcional.

let partialUser: PartialUser = {
  id: 1,
  name: 'Benjamin Hernández',
  // Podemos omitir `email` y `phoneNumber` ya que son opcionales en `PartialUser`
};

console.log(partialUser); // { id: 1, name: 'Benjamin Hernández' }

Hemos usado Partial para hacer que todas las propiedades de User sean opcionales. Por lo tanto, el nuevo tipo PartialUser tiene las propiedades id, name, email y phoneNumber, pero todas ellas son opcionales.

Required type en TypeScript

Empleamos la siguiente expresión para definir un Required type: Required<T>. Esto genera un nuevo tipo que tiene todas las propiedades de T, pero cada atributo es obligatoria. Veamos un ejemplo:

interface User {
  id: number;
  name: string;
  email?: string;
  phoneNumber?: string;
}

// Usando `Required` para hacer todas las propiedades de User obligatorias
type RequiredUser = Required<User>;

// `RequiredUser` es ahora un tipo con todas las propiedades de `User`, pero cada una de ellas es obligatoria.

let requiredUser: RequiredUser = {
  id: 1,
  name: 'Fatima Fernández',
  email: '[email protected]',
  phoneNumber: '343-545-789'
  // No podemos omitir `email` y `phoneNumber` ya que son obligatorias en `RequiredUser`
};

console.log(requiredUser); // { id: 1, name: 'Fatima Fernández', email: '[email protected]', phoneNumber: '343-545-789' }

Hemos empleado Required para hacer que todas las propiedades de User sean obligatorias. Por lo tanto, el nuevo tipo RequiredUser tiene las propiedades id, name, email y phoneNumber, pero todas ellas son obligatorias.

Contribución creada por: Martín Álvarez (Platzi Contributor).

Aportes 14

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Partial & Required en TS

Estos dos tipos de datos nos sirven para declarar que todos los campos de una interfaz son opcionales u obligatorios.

interface Product {
    title: string;
    price: number;
    category: string;
    size?: string;
}

type UpdateProduct = Partial<Product>
type StrictProduct = Required<Product>

De esa forma en UpdateProduct, todos los valores de Product van a ser opcionales y a la inversa en el caso de StrictProduct

Les comparto mis apuntes. 😄

Partial

Nos permite colocar todos los parámetros de una interface como opcionales, sin necesidad que colocar ? parámetro por parámetro.

Sintaxis

interface InterfaceName extends Partial<Interface> {
		statements
}

type TypeName = Partial<TypeOrInterface>;

Required

Nos permite colocar todos los parámetros de una interface como obligatorios.

Sintaxis

interface InterfaceName extends Required<Interface> {
		statements
}

type TypeName = Required<TypeOrInterface>;

Reutilización de DTOs

Podemos reutilizar nuestro DTO normalmente, ya que son interfaces.

Ejemplo

import { Product } from "./product.model";

export interface CreateProductDto extends Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'category'> {
    categoryId: string;
}

export interface UpdateProductDto extends Partial<CreateProductDto> {

}

Tener en cuenta que cuando utilizamos CreateProductDTO tenemos omitidos el atributo updateAt que será necesario para el método de actualizar producto, en tonces al hacer lo siguiente:

export interface UpdateProductDTO extends Partial<CreateProductDTO> {}

estamos heredando la omisión de updateAt y para recuperar esto podemos hacer una extención de múltiple de lo que teníamos anteriormente más el atributo updateAt que será necesario cuando actualicemos nuestro producto:

export interface UpdateProductDTO extends Partial<CreateProductDTO>, Pick<Product, 'updateAt'> {}

De verdad que el curso de manipulación de arrays debe estar genial. Es lo que tomaré al finalizar acá.

Aprender todo esto de utility types me recuerda mucho a teoría de conjuntos, donde cada interface seria un conjunto y sus operaciones como intersecciones o uniones los utility types

Nos sirven para declarar que los datos que provienen de ese tipo o interfaz son opcionales, usualmente lo usamos al momento de modificar datos.

Imagina que tienes un producto, este producto al momento de ser creado obtuvo ciertos datos, pero ahora necesitas modificarlo, sin embargo no necesitas todos los datos para modificarlo ya que solo modificaras o cambiaras ciertos datos.

Entonces allí entra Partials

interface Product {
	id: number,
	name: string,
	color: string,
	description: string,
	model: string,
	country: string,
}

interface EditProduct extends Product Partial<Product>

Required

A diferencia de Partials que pone todos los datos como opcionales, tenemos también required que hace lo contrario, pone todos los datos como obligatorios.

En TypeScript, `Partial` y `Required` son utilidades de tipos que modifican las propiedades de un tipo de objeto. Aquí se describen sus diferencias y cómo se utilizan. ### `Partial` en TypeScript La utilidad `Partial` convierte todas las propiedades de un tipo en opcionales. Esto es útil cuando necesitas trabajar con objetos que pueden no tener todas sus propiedades definidas. #### Ejemplo de `Partial` ![](https://static.platzi.com/media/user_upload/partial-0faf93c5-9e96-4ea5-b3ed-c0e4d6fda627.jpg) En este ejemplo, `Partial<User>` permite que el objeto `fieldsToUpdate` tenga cualquiera de las propiedades de `User` pero no es necesario que tenga todas. ### `Required` en TypeScript La utilidad `Required` convierte todas las propiedades de un tipo en obligatorias. Esto es útil cuando necesitas asegurarte de que todas las propiedades de un tipo están presentes. #### Ejemplo de `Required` #### ![](https://static.platzi.com/media/user_upload/requiered-50dbf05e-0df3-41ec-b544-3a88deadcce2.jpg) En este ejemplo, `Required<User>` asegura que todas las propiedades del objeto `user` deben estar presentes y definidas. ### Diferencias Clave 1. **Funcionalidad**: * `Partial<T>`: Convierte todas las propiedades de `T` en opcionales. * `Required<T>`: Convierte todas las propiedades de `T` en obligatorias. 2. **Usos Comunes**: * `Partial`: Se utiliza cuando se trabaja con objetos que pueden estar incompletos o cuando se actualizan solo algunas propiedades de un objeto. * `Required`: Se utiliza cuando se necesita garantizar que un objeto tiene todas sus propiedades definidas. 3. **Tipos Originales**: * `Partial` se aplica sobre tipos que tienen propiedades obligatorias, haciéndolas opcionales. * `Required` se aplica sobre tipos que pueden tener propiedades opcionales, haciéndolas obligatorias.
En el método updateProduct se quiere buscar al producto por medio del id para actualizarlo, el profesor lo dejo solamente con el tipado :string pero en base.model.ts esta tipado como id: string | number. Hay que adicionarle el tipado number al id, para que no genere error en el main.ts ```js export const updateProduct = (id: string |number , changes: updateProductDto): Product =>{ ```
Me he estado informando y creo que no hay una solución directa para convertir solo algunos campos opcionales en obligatorios utilizando Required y a la vez mantener el resto de atributos como están. Sin embargo, he dado con un par de soluciones: ```js //Solución 1 export interface RequiredAttributes extends Required<Pick<CreateProductDto, 'size' | 'color'>>, Omit<CreateProductDto, 'size' | 'color'> {} //Solución 2 export interface RequiredAttributes extends Omit<CreateProductDto, 'size' | 'color'> { size: Sizes; color: string; } //Solución para "type" type RequiredType = Required<Pick<CreateProductDto, 'size' | 'color'>> & CreateProductDto; ```La primera solución consiste en extender de dos interfaces, una que recoge los atributos "size" y "color" y los convierte en atributos requeridos, y la otra interfaz que omite los campos "size" y "color". De esta forma en la nueva interfaz se haría una especie de unión entre estas dos interfaces. En la segunda solución extendemos de la interfaz original, pero omitiendo los campos opcionales y volviéndolos a añadir en la nueva interfaz, pero evitando que sean opcionales. La última solución es prácticamente como la primera pero aplicada a "type" en vez de a interfaces. ¡Espero que les sirva de ayuda! 💚 PD: he hecho opcional el campo "color" solo para este ejemplo.

en lugar del find puede ser un map.

const updateProduct = (id: string, payload: IUpdateProductDto) => {
    const updatedProducts = products.map(item => {
        return (item.id === id)? {...item, ...payload}: item
    })
    return updatedProducts
  }

En 8:52 Cuando se hace:

const prevData = productos[index]
products[index] = {
...prevData, ...changs
}

No es necesario el prevData, esta variable apunta al objeto en el array, no guarda una copia

Ya terminando la clase me perdi jejej
se confundio en el minuto 10

Lo que comentaba el profe sobre prevData y changes es muy importante en la vida real para no tener perdida de información y no tener que restaurar un respaldo de la base de datos. Si algo así te pasa y no tienes un respaldo… estas en problemas.
Aquí un pequeño ejemplo de lo que menciona el profe con una API con Express:

router.put('/:ID', verify, async function (req, res) {
    try {
        const { ID } = req.params
        const clientesJSON = { ...req.body, ID }

        const item = await service.updateClientes(clientesJSON)
        res.json({
            message: 'Test api updated',
            item,
        })
    } catch (error) {
        res.status(404).json({ message: error.message })
    }
})

Podemos hacer que los campos sean opcionales con Partial

export interface UpdateProductDto extends Partial<CreateProductDto> {}

Y podemos hacer que sean obligatorios con Required

type example2 = Required<Product>