Biblioteca TypeScript com tipos utilitários, decorators e funções genéricas para desenvolvimento moderno.
O objetivo do projeto é criar uma biblioteca de utilitários reutilizáveis com tipos avançados, decorators e funções genéricas.
# Clone o repositório
git clone https://github.com/seu-usuario/type-utilities-lib.git
cd type-utilities-lib
# Instale as dependências
npm install
# Rode os testes
npm test
# Build do projeto
npm run build
# Desenvolvimento
npm run dev- Node.js >= 18.x
- TypeScript >= 5.0
Localização: src/types/index.ts
Permite que um tipo aceite null.
import { Nullable } from './types'
type Username = Nullable<string> // string | null
const validUsername: Username = "john_doe" // ✓ OK
const noUsername: Username = null // ✓ OKTorna todas as propriedades opcionais recursivamente.
import { DeepPartial } from './types'
interface User {
profile: {
address: {
street: string
city: string
}
}
}
// Tudo opcional, incluindo campos aninhados
type PartialUser = DeepPartial<User>
const user: PartialUser = {
profile: {} // ✓ OK - não precisa de address
}Torna todas as propriedades obrigatórias recursivamente.
import { DeepRequired } from './types'
interface Config {
database?: {
host?: string
port?: number
}
}
// Agora tudo é obrigatório
type RequiredConfig = DeepRequired<Config>
const config: RequiredConfig = {
database: {
host: "localhost", // ✓ Obrigatório
port: 5432 // ✓ Obrigatório
}
}Torna todas as propriedades readonly recursivamente.
import { ReadonlyDeep } from './types'
interface User {
profile: {
name: string
}
}
type ImmutableUser = ReadonlyDeep<User>
const user: ImmutableUser = {
profile: { name: "John" }
}
user.profile.name = "Jane" // ❌ Error: readonly"Achata" tipos interseccionados para melhor legibilidade.
import { Prettyfi } from './types'
type A = { a: number }
type B = { b: string }
// Sem Prettyfi: difícil de ler no editor
type Ugly = A & B
// Com Prettyfi: apresentação limpa
type Clean = Prettyfi<A & B>
// Resultado: { a: number; b: string }Seleciona apenas as propriedades de T cujo tipo estende U.
import { PickByType } from './types'
interface Product {
id: number
name: string
description: string
price: number
inStock: boolean
tags: string[]
}
// Pegar apenas propriedades string
type ProductStrings = PickByType<Product, string>
// Resultado: { name: string; description: string }
// Pegar apenas propriedades number
type ProductNumbers = PickByType<Product, number>
// Resultado: { id: number; price: number }
// Útil para criar DTOs específicos
function createProductLabel(data: ProductStrings) {
return `${data.name}: ${data.description}`
}
// Extrair apenas campos numéricos para cálculos
function calculateDiscount(data: ProductNumbers) {
return data.price * 0.1
}Remove as propriedades de T cujo tipo estende U.
import { OmitByType } from './types'
interface Product {
id: number
name: string
description: string
price: number
inStock: boolean
tags: string[]
}
// Remover todas as propriedades number
type ProductWithoutNumbers = OmitByType<Product, number>
// Resultado: { name: string; description: string; inStock: boolean; tags: string[] }
// Remover todas as propriedades string
type ProductWithoutStrings = OmitByType<Product, string>
// Resultado: { id: number; price: number; inStock: boolean; tags: string[] }
// Criar DTO público sem IDs numéricos sensíveis
function toPublicProduct(product: Product): OmitByType<Product, number> {
const { id, price, ...rest } = product
return rest
}Localização: src/decorators/index.ts
⚠️ Nota: Decorators requeremexperimentalDecorators: truenotsconfig.json
Mede o tempo de execução de métodos e loga informações.
import { MeasureTime } from './decorators'
class UserService {
@MeasureTime()
async fetchUser(id: string) {
await new Promise(resolve => setTimeout(resolve, 1000))
return { id, name: "John Doe" }
}
}
const service = new UserService()
await service.fetchUser("user-123")
// Output no console:
// [fetchUser] argumentos recebidos: ['user-123']
// [fetchUser] retornado: { id: 'user-123', name: 'John Doe' }
// [fetchUser] duração: 1002msUso Prático:
- Debug de performance
- Identificar métodos lentos
- Monitorar chamadas em desenvolvimento
Localização: src/utils/index.ts
Tenta executar uma função assíncrona múltiplas vezes antes de falhar.
import { retry } from './utils'
// Função que pode falhar
const fetchData = async () => {
const response = await fetch("https://api.example.com/data")
if (!response.ok) throw new Error("API Error")
return response.json()
}
// Tentar 3 vezes com 1 segundo de delay entre tentativas
const data = await retry(fetchData, 3, 1000)
// Se todas as 3 tentativas falharem, lança o erroParâmetros:
fn: Função assíncrona a ser executadaretries: Número de tentativas (padrão: 3)delay: Tempo em ms entre tentativas (padrão: 1000)
Casos de Uso:
- Requisições HTTP instáveis
- Operações de I/O que podem falhar
- Integrações com APIs externas
# Rodar todos os testes
npm test
# Modo watch (re-executa ao salvar)
npm run test:watch
# Com relatório de coverage
npm run test:coverageLocalização: src/__tests__/retry.spec.ts
✓ deve retornar o valor na primeira tentativa se tudo der certo
✓ deve tentar novamente se falhar na primeira vez
✓ deve lançar erro se todas as tentativas falharem
File | % Stmts | % Branch | % Funcs | % Lines
---------------|---------|----------|---------|--------
utils/index.ts | 100 | 100 | 100 | 100
type-utilities-lib/
├── src/
│ ├── __tests__/
│ │ └── retry.spec.ts ✅ Implementado
│ ├── decorators/
│ │ └── index.ts ✅ MeasureTime
│ ├── types/
│ │ └── index.ts ✅ 5 tipos implementados
│ ├── utils/
│ │ └── index.ts ✅ retry
│ └── index.ts 🔴 Pendente (entry point)
├── dist/ (gerado após build)
├── coverage/ (gerado após test:coverage)
├── .gitignore ✅ Configurado
├── jest.config.js ✅ Configurado
├── package.json ✅ Scripts funcionais
├── tsconfig.json ✅ Decorators habilitados
└── README.md 📖 Este arquivo
- Setup TypeScript + Jest
- Tipos básicos: Nullable, DeepPartial, DeepRequired, ReadonlyDeep, Prettyfi
- Decorator: MeasureTime
- Função: retry com testes
- Configuração ESLint/Prettier
-
Tipos Adicionais:
-
Maybe<T>(T | undefined) -
Optional<T>(T | null | undefined) -
PickByType<T, U>(extrair props por tipo) -
OmitByType<T, U>(omitir props por tipo)
-
-
Decorators Adicionais:
-
@Cache(ttl)- cachear resultados -
@Validate(schema)- validação de argumentos -
@Retry(maxRetries)- retry automático -
@Log()- logging separado do MeasureTime
-
-
Funções Adicionais:
-
merge<T, U>()- merge com type safety -
deepClone<T>()- clone profundo -
pick<T, K>()- pick tipado -
omit<T, K>()- omit tipado
-
-
Testes:
-
types.spec.ts- testar todos os tipos -
decorators.spec.ts- testar todos decorators - Coverage >80%
-
- Entry point
src/index.tsexportando tudo - Documentação completa com mais exemplos
- Exemplos práticos em
examples/ - GitHub Actions CI/CD
import { retry } from './utils'
import { Nullable } from './types'
interface User {
id: string
email: string
}
async function getUser(id: string): Promise<Nullable<User>> {
return retry(async () => {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) throw new Error("Failed to fetch user")
return response.json()
}, 3, 1000)
}import { DeepPartial } from './types'
interface AppConfig {
database: {
host: string
port: number
credentials: {
user: string
password: string
}
}
}
// Função aceita config parcial
function updateConfig(changes: DeepPartial<AppConfig>) {
// Pode passar apenas o que quer mudar
console.log(changes)
}
updateConfig({
database: {
port: 5433 // ✓ Só mudando a porta
}
})import { MeasureTime } from './decorators'
class ProductService {
@MeasureTime()
async getProducts(category: string) {
// Automaticamente loga tempo e argumentos
await new Promise(r => setTimeout(r, 500))
return [{ id: 1, name: "Product 1" }]
}
}Este é um projeto de estudos, mas pull requests são bem-vindos!
# Fork e clone
git clone seu-fork
# Crie uma branch
git checkout -b feature/nova-funcionalidade
# Faça commits claros
git commit -m "feat(types): adiciona tipo Maybe<T>"
# Push e abra PR
git push origin feature/nova-funcionalidade- TypeScript Handbook - Advanced Types
- TypeScript Playground - Testar tipos online
- Exercism TypeScript Track
- type-fest - Inspiração para tipos
- ✨ Implementados 5 tipos utilitários
- ✨ Decorator MeasureTime funcional
- ✨ Função retry com testes completos
- 🧪 Jest configurado e funcionando
- 📚 README com documentação básica
Marcos k1ngS
- GitHub: @k1ngS
- LinkedIn: marcos-k1ngs
- Website: k1ngs.dev
- Email: marcos.beltrao@outlook.pt