fix: corrigir tipos e eliminar non-null assertions

Substitui non-null assertions (!) por type assertions ou optional
chaining com guards. Troca any por unknown/tipos explícitos.

- drizzle.config: DATABASE_URL! → as string
- use-form-state: Record<string, any> → Record<string, unknown>
- actions: catch (e: any) → catch (e), model tipado explicitamente
- pagadores/data: row: any → Record<string, unknown>
- note-dialog: result tipado explicitamente
- bulk-import: payload as any removido
- Map.get()! → optional chaining + guards em relatórios e dashboard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-02-26 17:22:41 +00:00
parent 8de22b9930
commit 803e273538
15 changed files with 59 additions and 26 deletions

View File

@@ -184,7 +184,7 @@ export async function updatePasswordAction(
success: true, success: true,
message: "Senha atualizada com sucesso", message: "Senha atualizada com sucesso",
}; };
} catch (authError: any) { } catch (authError) {
console.error("Erro na API do Better Auth:", authError); console.error("Erro na API do Better Auth:", authError);
// Verificar se o erro é de senha incorreta // Verificar se o erro é de senha incorreta

View File

@@ -599,7 +599,7 @@ export async function generateInsightsAction(
const aggregatedData = await aggregateMonthData(user.id, period); const aggregatedData = await aggregateMonthData(user.id, period);
// Selecionar provider // Selecionar provider
let model; let model: ReturnType<typeof google>;
// Se o modelo tem "/" é OpenRouter (formato: provider/model) // Se o modelo tem "/" é OpenRouter (formato: provider/model)
if (isOpenRouterFormat && !selectedModel) { if (isOpenRouterFormat && !selectedModel) {

View File

@@ -178,7 +178,7 @@ export async function createInstallmentAnticipationAction(
: totalAmount - discount; // Receita: 1000 - 20 = 980 : totalAmount - discount; // Receita: 1000 - 20 = 980
// 3. Pegar dados da primeira parcela para referência // 3. Pegar dados da primeira parcela para referência
const firstInstallment = installments[0]!; const firstInstallment = installments[0];
// 4. Criar lançamento e antecipação em transação // 4. Criar lançamento e antecipação em transação
await db.transaction(async (tx) => { await db.transaction(async (tx) => {

View File

@@ -258,7 +258,7 @@ export async function duplicatePreviousMonthBudgetsAction(
amount: b.amount, amount: b.amount,
period: data.period, period: data.period,
userId: user.id, userId: user.id,
categoriaId: b.categoriaId!, categoriaId: b.categoriaId as string,
})), })),
); );

View File

@@ -88,7 +88,7 @@ export async function fetchPagadorLancamentos(filters: SQL[]) {
.orderBy(desc(lancamentos.purchaseDate), desc(lancamentos.createdAt)); .orderBy(desc(lancamentos.purchaseDate), desc(lancamentos.createdAt));
// Transformar resultado para o formato esperado // Transformar resultado para o formato esperado
return lancamentoRows.map((row: any) => ({ return lancamentoRows.map((row: Record<string, unknown>) => ({
...row.lancamento, ...row.lancamento,
pagador: row.pagador, pagador: row.pagador,
conta: row.conta, conta: row.conta,

View File

@@ -192,7 +192,7 @@ export function NoteDialog({
} }
startTransition(async () => { startTransition(async () => {
let result; let result: { success: boolean; message?: string; error?: string };
if (mode === "create") { if (mode === "create") {
result = await createNoteAction(payload); result = await createNoteAction(payload);
} else { } else {

View File

@@ -163,7 +163,7 @@ export function BulkImportDialog({
: undefined, : undefined,
}; };
const result = await createLancamentoAction(payload as any); const result = await createLancamentoAction(payload);
if (result.success) { if (result.success) {
successCount++; successCount++;
@@ -360,7 +360,7 @@ export function BulkImportDialog({
</div> </div>
)} )}
<DialogFooter className="gap-3"> <DialogFooter>
<Button <Button
type="button" type="button"
variant="outline" variant="outline"

View File

@@ -591,7 +591,7 @@ export function LancamentosPage({
<AnticipateInstallmentsDialog <AnticipateInstallmentsDialog
open={anticipateOpen} open={anticipateOpen}
onOpenChange={setAnticipateOpen} onOpenChange={setAnticipateOpen}
seriesId={selectedForAnticipation.seriesId!} seriesId={selectedForAnticipation.seriesId as string}
lancamentoName={selectedForAnticipation.name} lancamentoName={selectedForAnticipation.name}
categorias={categoriaOptions.map((c) => ({ categorias={categoriaOptions.map((c) => ({
id: c.value, id: c.value,
@@ -610,7 +610,7 @@ export function LancamentosPage({
<AnticipationHistoryDialog <AnticipationHistoryDialog
open={anticipationHistoryOpen} open={anticipationHistoryOpen}
onOpenChange={setAnticipationHistoryOpen} onOpenChange={setAnticipationHistoryOpen}
seriesId={selectedForAnticipation.seriesId!} seriesId={selectedForAnticipation.seriesId as string}
lancamentoName={selectedForAnticipation.name} lancamentoName={selectedForAnticipation.name}
onViewLancamento={(lancamentoId) => { onViewLancamento={(lancamentoId) => {
const lancamento = lancamentos.find((l) => l.id === lancamentoId); const lancamento = lancamentos.find((l) => l.id === lancamentoId);

View File

@@ -5,6 +5,6 @@ export default {
out: "./drizzle", out: "./drizzle",
dialect: "postgresql", dialect: "postgresql",
dbCredentials: { dbCredentials: {
url: process.env.DATABASE_URL!, url: process.env.DATABASE_URL as string,
}, },
} satisfies Config; } satisfies Config;

View File

@@ -16,7 +16,9 @@ import { useState } from "react";
* updateField('name', 'John'); * updateField('name', 'John');
* ``` * ```
*/ */
export function useFormState<T extends Record<string, any>>(initialValues: T) { export function useFormState<T extends Record<string, unknown>>(
initialValues: T,
) {
const [formState, setFormState] = useState<T>(initialValues); const [formState, setFormState] = useState<T>(initialValues);
/** /**

View File

@@ -127,9 +127,9 @@ export async function fetchInstallmentAnalysis(
}; };
if (seriesMap.has(row.seriesId)) { if (seriesMap.has(row.seriesId)) {
const group = seriesMap.get(row.seriesId)!; const group = seriesMap.get(row.seriesId);
group.pendingInstallments.push(installmentDetail); group?.pendingInstallments.push(installmentDetail);
group.totalPendingAmount += amount; if (group) group.totalPendingAmount += amount;
} else { } else {
seriesMap.set(row.seriesId, { seriesMap.set(row.seriesId, {
seriesId: row.seriesId, seriesId: row.seriesId,

View File

@@ -64,6 +64,8 @@ type ContaSluggedOption = BaseSluggedOption & {
type CartaoSluggedOption = BaseSluggedOption & { type CartaoSluggedOption = BaseSluggedOption & {
kind: "cartao"; kind: "cartao";
logo: string | null; logo: string | null;
closingDay: string | null;
dueDay: string | null;
}; };
export type SluggedFilters = { export type SluggedFilters = {
@@ -160,6 +162,8 @@ export const toOption = (
logo?: string | null, logo?: string | null,
icon?: string | null, icon?: string | null,
accountType?: string | null, accountType?: string | null,
closingDay?: string | null,
dueDay?: string | null,
): SelectOption => ({ ): SelectOption => ({
value, value,
label: normalizeLabel(label), label: normalizeLabel(label),
@@ -170,6 +174,8 @@ export const toOption = (
logo: logo ?? null, logo: logo ?? null,
icon: icon ?? null, icon: icon ?? null,
accountType: accountType ?? null, accountType: accountType ?? null,
closingDay: closingDay ?? null,
dueDay: dueDay ?? null,
}); });
export const fetchLancamentoFilterSources = async (userId: string) => { export const fetchLancamentoFilterSources = async (userId: string) => {
@@ -252,6 +258,8 @@ export const buildSluggedFilters = ({
slug: contaCartaoSlugger(label), slug: contaCartaoSlugger(label),
kind: "cartao" as const, kind: "cartao" as const,
logo: cartao.logo ?? null, logo: cartao.logo ?? null,
closingDay: cartao.closingDay ?? null,
dueDay: cartao.dueDay ?? null,
}; };
}); });
@@ -378,7 +386,7 @@ export const buildLancamentoWhere = ({
ilike(lancamentos.condition, searchPattern), ilike(lancamentos.condition, searchPattern),
and(isNotNull(contas.name), ilike(contas.name, searchPattern)), and(isNotNull(contas.name), ilike(contas.name, searchPattern)),
and(isNotNull(cartoes.name), ilike(cartoes.name, searchPattern)), and(isNotNull(cartoes.name), ilike(cartoes.name, searchPattern)),
)!, ) as SQL,
); );
} }
@@ -501,8 +509,20 @@ export const buildOptionSets = ({
: cartaoFiltersRaw; : cartaoFiltersRaw;
const cartaoOptions = sortByLabel( const cartaoOptions = sortByLabel(
cartaoOptionsSource.map(({ id, label, slug, logo }) => cartaoOptionsSource.map(({ id, label, slug, logo, closingDay, dueDay }) =>
toOption(id, label, undefined, undefined, slug, undefined, logo), toOption(
id,
label,
undefined,
undefined,
slug,
undefined,
logo,
undefined,
undefined,
closingDay,
dueDay,
),
), ),
); );

View File

@@ -123,12 +123,16 @@ export async function fetchCategoryChartData(
}); });
} }
categoryMap.get(categoryId)!.dataByPeriod.set(period, amount); categoryMap.get(categoryId)?.dataByPeriod.set(period, amount);
} }
const chartData = periods.map((period) => { const chartData = periods.map((period) => {
const [year, month] = period.split("-"); const [year, month] = period.split("-");
const date = new Date(Number.parseInt(year, 10), Number.parseInt(month, 10) - 1, 1); const date = new Date(
Number.parseInt(year, 10),
Number.parseInt(month, 10) - 1,
1,
);
const monthLabel = format(date, "MMM", { locale: ptBR }).toUpperCase(); const monthLabel = format(date, "MMM", { locale: ptBR }).toUpperCase();
const dataPoint: { month: string; [key: string]: number | string } = { const dataPoint: { month: string; [key: string]: number | string } = {
@@ -144,7 +148,11 @@ export async function fetchCategoryChartData(
const months = periods.map((period) => { const months = periods.map((period) => {
const [year, month] = period.split("-"); const [year, month] = period.split("-");
const date = new Date(Number.parseInt(year, 10), Number.parseInt(month, 10) - 1, 1); const date = new Date(
Number.parseInt(year, 10),
Number.parseInt(month, 10) - 1,
1,
);
return format(date, "MMM", { locale: ptBR }).toUpperCase(); return format(date, "MMM", { locale: ptBR }).toUpperCase();
}); });

View File

@@ -98,7 +98,8 @@ export async function fetchCategoryReport(
}); });
} }
const categoryItem = categoryMap.get(categoryId)!; const categoryItem = categoryMap.get(categoryId);
if (!categoryItem) continue;
// Add monthly data (will calculate percentage later) // Add monthly data (will calculate percentage later)
categoryItem.monthlyData.set(period, { categoryItem.monthlyData.set(period, {
@@ -122,7 +123,8 @@ export async function fetchCategoryReport(
for (let i = 0; i < sortedPeriods.length; i++) { for (let i = 0; i < sortedPeriods.length; i++) {
const period = sortedPeriods[i]; const period = sortedPeriods[i];
const monthlyData = categoryItem.monthlyData.get(period)!; const monthlyData = categoryItem.monthlyData.get(period);
if (!monthlyData) continue;
if (i > 0) { if (i > 0) {
// Get previous period data // Get previous period data

View File

@@ -164,7 +164,8 @@ export async function fetchTopEstabelecimentosData(
c.establishmentName === est.name && c.categoriaId, c.establishmentName === est.name && c.categoriaId,
) )
.map((c: CategoryByEstRow) => ({ .map((c: CategoryByEstRow) => ({
name: categoryMap.get(c.categoriaId!)?.name || "Sem categoria", name:
categoryMap.get(c.categoriaId as string)?.name || "Sem categoria",
count: Number(c.count) || 0, count: Number(c.count) || 0,
})) }))
.sort( .sort(
@@ -222,9 +223,9 @@ export async function fetchTopEstabelecimentosData(
const topCategories: TopCategoryData[] = topCategoriesData const topCategories: TopCategoryData[] = topCategoriesData
.filter((c: TopCategoryRow) => c.categoriaId) .filter((c: TopCategoryRow) => c.categoriaId)
.map((cat: TopCategoryRow) => { .map((cat: TopCategoryRow) => {
const catInfo = categoryMap.get(cat.categoriaId!); const catInfo = categoryMap.get(cat.categoriaId as string);
return { return {
id: cat.categoriaId!, id: cat.categoriaId as string,
name: catInfo?.name || "Sem categoria", name: catInfo?.name || "Sem categoria",
icon: catInfo?.icon || null, icon: catInfo?.icon || null,
totalAmount: Math.abs(safeToNumber(cat.totalAmount)), totalAmount: Math.abs(safeToNumber(cat.totalAmount)),