TypeScript: Omit

Opublikowano: 26.04.2022 - tagi: TypeScript JavaScript

Omit tworzy nowy typ danych na podstawie już istniejącego. Przydaje się szczególnie wtedy kiedy chcemy się pozbyć niektórych pól ze wzorca.

Składania wygląda następująco:

Omit<Type, Keys>

Pierwszy parametr Type to istniejący typ danych. Drugi: Keys to pole lub pola, które nie zostaną wzięte pod uwagę, w nowo stworzonym typie danych.

Jest dostępny w TypeScript od wersji 3.5

Przykłady

Przykład 1

interface Book {
	title: string;
	author: string;
	pages: number;
}

type AudioBook = Omit<Book, 'pages'>;

// AudioBook będzie wyglądać tak:
/*
AudioBook {
	title: string;
	author: string;
}
*/

Mamy nowy typ AudioBook bez pola pages.

Przykład 2

Jeśli chcemy pozbyć się więcej niż jedno pole, piszemy:

interface Book {
	title: string;
	author: string;
	pages: number;
	weight: number;
}

type eBook = Omit<Book, 'pages' | 'weight'>;

// eBook będzie wyglądać tak:
/*
eBook {
	title: string;
	author: string;
}
*/

Przykład 3

Za pomocą Omit możemy także rozszerzać interfejsy:

interface Book {
	title: string;
	author: string;
	pages: number;
	weight: number;
}

interface AudioBook extends Omit<Book, 'pages' | 'weight'> {
	length: number;
}

// Interfejs AudioBook będzie wyglądać tak:
/*
interface AudioBook {
	title: string;
	author: string;
	length: number;
}
*/

Przykład 4

Dzięki Omit możemy też "nadpisać" dane pole:

interface Book {
	id: string;
	title: string;
	author: string;
}

interface AudioBook extends Omit<Book, 'id'> {
	id: number;
}

// Interfejs AudioBook będzie wyglądać tak:
/*
interface AudioBook {
	id: number;
	title: string;
	author: string;
}
*/

W interfejsie Book mamy pole id o typie string. A w nowym typie AudioBook potrzebujemy wszystkie pola z Book tylko pole id powinno być typu number. Dzięki Omit jak widać, można to łatwo osiągnąć.


MongoDB: Jak sprawdzić czy pole ma daną wartość lub null?

Opublikowano: 21.04.2022 - tagi: MongoDB Baza danych Zapytanie

Załóżmy, że mamy taki model danych:

{
	title: string,
	status: string | null
}

Poniżej przykład danych na podstawie tego modelu:

[
	{
		title: "Status Draft"
		status: "draft"
	}
	{
		title: "Status Null"
		status: null
	},
	{
		title: "Status Closed"
		status: "closed"
	}
]

I teraz potrzebujemy napisać zapytanie, które pobierze nam dane na podstawie pola status: pobierz rekordy dla wartości X lub dla null.

Wystarczy napisać:

db.find({
  $or: [
		{ 
			status: { $eq: 'draft' }
		},
		{
			status: { $type: 'null' } 
		}
	]
})

Korzystamy tutaj z operatora $or: sprawdzamy najpierw, czy istnieją rekordy o podanej wartości i dodatkowo informujemy za pomocą $type, że chcemy pobrać także rekordy z wartością null.

W tym przypadku zwróci dwa rekordy:

[
	{
		title: "Status Draft"
		status: "draft"
	}
	{
		title: "Status Null"
		status: null
	}
]

JavaScript: Jak usunąć duplikaty z tablicy?

Opublikowano: 19.04.2022 - tagi: JavaScript Tablica Duplikat

Jest kilka sposobów na rozwiązanie tego problemu. Tutaj podaję jeden z nich:

const data = [1, 2, 3, 1, 7, 7, 5, 1, 8, 9];

const removeDuplicates = (someData) => {
  return Array.from(new Set(someData));
};

console.log('data: ', removeDuplicates(data)); // [1, 2, 3, 7, 5, 8, 9]

Najpierw przekazujemy tablicę do klasy Set dzięki, której pozbędziemy się duplikatów. Na koniec przy użyciu metody from z klasy Array zamieniamy obiekt Set w tablicę.


RxJS: Operator pluck

Opublikowano: 12.04.2022 - tagi: JavaScript RxJS Operator Pipe

Operator pluck działa bardzo podobnie do opisanego operatora map.

Jeśli potrzebujemy wyłuskać dane z jednej właściwości, ten operator idealnie się do tego nadaje.

Przykłady

Przykład 1

import { from } from 'rxjs';
import { pluck } from 'rxjs/operators';

const data = [
    {
        title: 'Foo',
        value: 1
    },
    {
        title: 'Bar',
        value: 2
    }
];

const observable = from(data).pipe(
    pluck('title')
);
observable.subscribe(console.log);
// Wynik
// Foo
// Bar

Przykład 2

Za pomocą operatora pluck możemy też pobrać zagnieżdżone wartości:

import { from } from 'rxjs';
import { pluck } from 'rxjs/operators';

const data = [
    {
        title: 'Foo',
        value: {
            amount: 100,
            currency: 'PLN'
        }
    },
    {
        title: 'Bar',
        value: {
            amount: 700,
            currency: 'EUR'
        }
    }
];

const observable = from(data).pipe(
    pluck('value', 'currency')
);
observable.subscribe(console.log);
// Wynik
// PLN
// EUR

NodeJS: Mongoose jak sprawdzić czy podano tablicę w modelu danych?

Opublikowano: 05.04.2022 - tagi: NodeJS MongoDB Mongoose Walidacja Model Tablica JavaScript

W jednym z poprzednich wpisów pisałem o walidacji danych w bibliotece Mongoose.

Dzisiaj opiszę konkretny przypadek: jak sprawdzić, czy przekazano do modelu tablicę, która jest wymagana?

Sprawdzanie tablicy

Załóżmy, że mam taki model danych:

const PostSchema = new Schema({
title: { type: String, required: true },
tags: { type: [String], required: true }
});
const PostModel = mongoose.model('post', PostSchema);

Definiujemy model danych, w którym mamy dwa parametry: title i tags. Oba są wymagane. Przy czym title to zwykły ciąg znaków, a tags to zwykła tablica tekstowa.

Poniżej znajduje się fragment kodu, który sprawdza poprawność danych w modelu i próbuje dodać nowy rekord do bazy danych:

const newEntry = PostModel({ title: 'Some entry' });

const validateErrors = newEntry.validateSync(); 
console.log('validateErrors: ', validateErrors);

try {
  await PostModel.create(newEntry);
} catch(error) {
  console.log('error: ', error);
}

Pytanie: czy metoda validateSync powinna zwrócić jakieś błędy/błąd walidacji? Czy wszystko tutaj jest ok? Do modelu przekazujemy jedno pole: title, które jest wymagane. Nie przekazaliśmy jednak pola: tags, które także jest wymagane. Więc odpowiedź jest prosta! Zwróci błąd walidacji!

To nieprawda. Rekord zostanie dodany do bazy.

Jak to możliwe?

Walidacja wymaganej tablicy

Żeby dowiedzieć się, co się stało, sprawdźmy zawartość bazy danych. Okazuje się, że pole tags to pusta tablica!

Jeśli w modelu danych zdefiniowaliśmy typ tablica i przy tworzeniu rekordu pominiemy to pole, w takim przypadku zostanie umieszczona pusta tablica.

A co zrobić jeśli chcemy jednak wymagać podania tablicy? Prosta rzecz:

...
tags: { type: [String], required: true, default: undefined }

Definiujemy dodatkowe pole: default i ustawiamy je na undefined. Po tej zmianie zostanie zgłoszony błąd walidacji, a rekord nie zostanie dodany do bazy danych.