Pular para o conteúdo principal

TypeGuard

O TypeGuard é a classe central para verificação de tipos em tempo de execução. Ele substitui completamente o uso manual de typeof, instanceof e verificações ad-hoc no projeto.

Regra do projeto: nunca use typeof diretamente para validação de tipos primitivos. Use sempre TypeGuard.

import { TypeGuard } from "tyforge";

Verificação de tipos

Todos os métodos de verificação recebem (value: unknown, fieldPath: string) e retornam Result<true, ExceptionValidation>. A exceção é isString, que retorna Result<string, ExceptionValidation> com o valor já trimado.

isString

Verifica se o valor é uma string, aplica trim() e valida comprimento.

static isString(
value: unknown,
fieldPath: string,
min?: number, // padrão: 1
max?: number, // padrão: Number.MAX_SAFE_INTEGER
): Result<string, ExceptionValidation>

Retorna a string trimada no campo value em caso de sucesso:

const result = TypeGuard.isString(input, "name", 1, 100);
if (result.success) {
const trimmed: string = result.value; // string já sem espaços extras
}

isNumber

Verifica se o valor é um número válido (não NaN), com limites opcionais e precisão decimal.

static isNumber(
value: unknown,
fieldPath: string,
min?: number, // padrão: Number.MIN_SAFE_INTEGER
max?: number, // padrão: Number.MAX_SAFE_INTEGER
decimalPrecision?: number, // padrão: Infinity
): Result<true, ExceptionValidation>
const result = TypeGuard.isNumber(price, "price", 0, 99999, 2);

isInteger

Verifica se o valor é um inteiro (Number.isInteger), com limites opcionais. Delega para isNumber com decimalPrecision = 0.

static isInteger(
value: unknown,
fieldPath: string,
min?: number,
max?: number,
): Result<true, ExceptionValidation>

isPositiveInteger / isNegativeInteger

Atalhos para isInteger com limites pré-definidos:

TypeGuard.isPositiveInteger(value, "count");   // min = 0
TypeGuard.isNegativeInteger(value, "offset"); // max = -1

isPositiveNumber / isNegativeNumber

Atalhos para isNumber com limites pré-definidos e precisão decimal opcional:

TypeGuard.isPositiveNumber(value, "amount", 2); // min = 0, decimalPrecision = 2
TypeGuard.isNegativeNumber(value, "debt", 2); // max = -MIN_VALUE

isBoolean

Verifica se o valor é um booleano (typeof value === "boolean").

static isBoolean(value: unknown, fieldPath: string): Result<true, ExceptionValidation>

isObject

Verifica se o valor é um objeto não-nulo e não-array.

static isObject(value: unknown, fieldPath: string): Result<true, ExceptionValidation>

isArray

Verifica se o valor é um array com limites opcionais de tamanho.

static isArray(
value: unknown,
fieldPath: string,
min?: number, // padrão: 0
max?: number, // padrão: Number.MAX_SAFE_INTEGER
): Result<true, ExceptionValidation>

isDate

Verifica se o valor é uma instância de Date válida (!isNaN(date.getTime())).

static isDate(value: unknown, fieldPath: string): Result<true, ExceptionValidation>

isFunction

Verifica se o valor é uma função.

static isFunction(value: unknown, fieldPath: string): Result<true, ExceptionValidation>

isNull / isUndefined

Verificam se o valor é exatamente null ou undefined.

static isNull(value: unknown, fieldPath: string): Result<true, ExceptionValidation>
static isUndefined(value: unknown, fieldPath: string): Result<true, ExceptionValidation>

isRegExp / isSymbol / isBigInt / isSet / isMap

Verificações para tipos especializados:

static isRegExp(value: unknown, fieldPath: string): Result<true, ExceptionValidation>
static isSymbol(value: unknown, fieldPath: string): Result<true, ExceptionValidation>
static isBigInt(value: unknown, fieldPath: string): Result<true, ExceptionValidation>
static isSet(value: unknown, fieldPath: string): Result<true, ExceptionValidation>
static isMap(value: unknown, fieldPath: string): Result<true, ExceptionValidation>

Type narrowing

Métodos que funcionam como type guards nativos do TypeScript (retornam boolean com narrowing):

isRecord

Verifica se o valor é um Record<string, unknown>. Funciona como type guard para narrowing:

static isRecord(value: unknown): value is Record<string, unknown>
if (TypeGuard.isRecord(data)) {
// TypeScript sabe que data é Record<string, unknown>
const name = data["name"];
}

isCallable

Verifica se o valor é uma função. Funciona como type guard:

static isCallable(value: unknown): value is Function
if (TypeGuard.isCallable(handler)) {
handler(); // TypeScript sabe que handler é Function
}

Extração de valores

Métodos que retornam Result<T, ExceptionValidation> com o valor tipado, não apenas Result<true>. Úteis quando você precisa do valor extraído após a validação.

extractBoolean

Extrai um booleano, retornando o valor tipado:

static extractBoolean(value: unknown, fieldPath: string): Result<boolean, ExceptionValidation>
const result = TypeGuard.extractBoolean(input, "active");
if (result.success) {
const active: boolean = result.value;
}

extractArray

Extrai um array com limites opcionais de tamanho:

static extractArray(
value: unknown,
fieldPath: string,
min?: number,
max?: number,
): Result<unknown[], ExceptionValidation>
const result = TypeGuard.extractArray(input, "tags", 1, 10);
if (result.success) {
const tags: unknown[] = result.value;
}

extractNumber

Extrai um número com limites opcionais:

static extractNumber(
value: unknown,
fieldPath: string,
min?: number,
max?: number,
): Result<number, ExceptionValidation>
const result = TypeGuard.extractNumber(input, "age", 0, 150);
if (result.success) {
const age: number = result.value;
}

Validação de enum

isEnumKey

Verifica se um valor é uma chave válida de um objeto enum:

static isEnumKey<T extends object>(
enumObj: T,
value: string | number,
fieldPath: string,
): Result<true, ExceptionValidation>
const OStatus = { ACTIVE: "active", INACTIVE: "inactive" } as const;

TypeGuard.isEnumKey(OStatus, "ACTIVE", "status"); // ok(true)
TypeGuard.isEnumKey(OStatus, "active", "status"); // err(...)

isEnumValue

Verifica se um valor é um valor válido de um objeto enum:

static isEnumValue<T extends object>(
enumObj: T,
value: string | number,
fieldPath: string,
): Result<true, ExceptionValidation>
const OStatus = { ACTIVE: "active", INACTIVE: "inactive" } as const;

TypeGuard.isEnumValue(OStatus, "active", "status"); // ok(true)
TypeGuard.isEnumValue(OStatus, "ACTIVE", "status"); // err(...)

Utilitários

isEmpty

Verifica se um valor está "vazio". Suporta múltiplos tipos:

static isEmpty(value: unknown): boolean
TipoConsiderado vazio
null, undefinedSempre
stringApós trim(), se o comprimento for 0
ArraySe length === 0
Set, MapSe size === 0
objectSe não possui chaves próprias
TypeGuard.isEmpty(null);        // true
TypeGuard.isEmpty(""); // true
TypeGuard.isEmpty(" "); // true
TypeGuard.isEmpty([]); // true
TypeGuard.isEmpty({}); // true
TypeGuard.isEmpty(new Set()); // true
TypeGuard.isEmpty("hello"); // false
TypeGuard.isEmpty([1]); // false

isHex

Verifica se o valor é um hexadecimal com prefixo 0x, com comprimento de dígitos útil opcional:

static isHex(
value: unknown,
fieldPath: string,
length?: number, // dígitos úteis (sem contar "0x")
): Result<true, ExceptionValidation>
TypeGuard.isHex("0x1a2b", "hash");         // ok(true)
TypeGuard.isHex("0x1a2b", "hash", 4); // ok(true) — 4 dígitos
TypeGuard.isHex("0x1a2b", "hash", 8); // err(...) — esperava 8
TypeGuard.isHex("hello", "hash"); // err(...)

Resumo de assinaturas

MétodoRetornoDescrição
isStringResult<string>String trimada com limites de comprimento
isNumberResult<true>Número com faixa e precisão decimal
isIntegerResult<true>Inteiro com faixa
isPositiveIntegerResult<true>Inteiro positivo ou zero
isNegativeIntegerResult<true>Inteiro negativo
isPositiveNumberResult<true>Número positivo ou zero com precisão
isNegativeNumberResult<true>Número negativo com precisão
isBooleanResult<true>Booleano
isObjectResult<true>Objeto não-nulo, não-array
isArrayResult<true>Array com limites de tamanho
isDateResult<true>Date válido
isFunctionResult<true>Função
isNullResult<true>Exatamente null
isUndefinedResult<true>Exatamente undefined
isRegExpResult<true>Expressão regular
isSymbolResult<true>Symbol
isBigIntResult<true>BigInt
isSetResult<true>Set
isMapResult<true>Map
isRecordvalue is RecordType guard para Record
isCallablevalue is FunctionType guard para Function
extractBooleanResult<boolean>Extrai booleano tipado
extractArrayResult<unknown[]>Extrai array tipado
extractNumberResult<number>Extrai número tipado
isEnumKeyResult<true>Chave de enum
isEnumValueResult<true>Valor de enum
isEmptybooleanVerificação de vazio
isHexResult<true>Hexadecimal com prefixo 0x