@lucasbernardosn/ts-utils 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/dev/index.d.ts +2 -0
- package/dist/dev/index.js +2 -0
- package/dist/dev/sleep.d.ts +32 -0
- package/dist/dev/sleep.js +42 -0
- package/dist/dev/sleep.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +9 -0
- package/dist/types/any.d.ts +33 -0
- package/dist/types/any.js +0 -0
- package/dist/types/array.d.ts +33 -0
- package/dist/types/array.js +0 -0
- package/dist/types/deep-keys-flat.d.ts +36 -0
- package/dist/types/deep-keys-flat.js +0 -0
- package/dist/types/deep-keys.d.ts +57 -0
- package/dist/types/deep-keys.js +0 -0
- package/dist/types/deep-partial.d.ts +39 -0
- package/dist/types/deep-partial.js +0 -0
- package/dist/types/deep-readonly.d.ts +39 -0
- package/dist/types/deep-readonly.js +0 -0
- package/dist/types/deep-value.d.ts +32 -0
- package/dist/types/deep-value.js +0 -0
- package/dist/types/ensure-string.d.ts +19 -0
- package/dist/types/ensure-string.js +0 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.js +0 -0
- package/dist/types/keys-of-type.d.ts +26 -0
- package/dist/types/keys-of-type.js +0 -0
- package/dist/types/merge-override.d.ts +34 -0
- package/dist/types/merge-override.js +0 -0
- package/dist/types/nullish.d.ts +25 -0
- package/dist/types/nullish.js +0 -0
- package/dist/types/omit-by-value.d.ts +31 -0
- package/dist/types/omit-by-value.js +0 -0
- package/dist/types/optional.d.ts +29 -0
- package/dist/types/optional.js +0 -0
- package/dist/types/pick-by-value.d.ts +30 -0
- package/dist/types/pick-by-value.js +0 -0
- package/dist/types/recompose.d.ts +26 -0
- package/dist/types/recompose.js +0 -0
- package/dist/types/required-except.d.ts +31 -0
- package/dist/types/required-except.js +0 -0
- package/dist/types/serializable-value.d.ts +23 -0
- package/dist/types/serializable-value.js +0 -0
- package/dist/types/strict-empty-object.d.ts +12 -0
- package/dist/types/strict-empty-object.js +0 -0
- package/dist/types/unknown.d.ts +33 -0
- package/dist/types/unknown.js +0 -0
- package/dist/types/value-of.d.ts +20 -0
- package/dist/types/value-of.js +0 -0
- package/dist/utils/compose-event-handlers.d.ts +18 -0
- package/dist/utils/compose-event-handlers.js +22 -0
- package/dist/utils/compose-event-handlers.js.map +1 -0
- package/dist/utils/create-split-props.d.ts +38 -0
- package/dist/utils/create-split-props.js +36 -0
- package/dist/utils/create-split-props.js.map +1 -0
- package/dist/utils/get-initials.d.ts +15 -0
- package/dist/utils/get-initials.js +21 -0
- package/dist/utils/get-initials.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/is-deep-equal.d.ts +24 -0
- package/dist/utils/is-deep-equal.js +110 -0
- package/dist/utils/is-deep-equal.js.map +1 -0
- package/dist/utils/is-not-nullish.d.ts +14 -0
- package/dist/utils/is-not-nullish.js +18 -0
- package/dist/utils/is-not-nullish.js.map +1 -0
- package/dist/utils/merge-booleans.d.ts +25 -0
- package/dist/utils/merge-booleans.js +37 -0
- package/dist/utils/merge-booleans.js.map +1 -0
- package/dist/utils/to-pascal-case.d.ts +18 -0
- package/dist/utils/to-pascal-case.js +17 -0
- package/dist/utils/to-pascal-case.js.map +1 -0
- package/package.json +41 -3
- package/README.md +0 -3
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/types/optional.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Tipo utilitário que torna propriedades específicas opcionais, mantendo as demais inalteradas.
|
|
4
|
+
*
|
|
5
|
+
* @template TBase - Tipo base de referência.
|
|
6
|
+
* @template TOptionalKeys - Chaves de TBase que se tornarão opcionais.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
*
|
|
10
|
+
* type Usuario = {
|
|
11
|
+
* id: number;
|
|
12
|
+
* nome: string;
|
|
13
|
+
* email: string;
|
|
14
|
+
* idade: number;
|
|
15
|
+
* };
|
|
16
|
+
*
|
|
17
|
+
* type UsuarioComIdOpcional = Optional<Usuario, 'id' | 'idade'>
|
|
18
|
+
*
|
|
19
|
+
* // Resultado:
|
|
20
|
+
* // {
|
|
21
|
+
* // id?: number;
|
|
22
|
+
* // nome: string;
|
|
23
|
+
* // email: string;
|
|
24
|
+
* // idade?: number;
|
|
25
|
+
* // }
|
|
26
|
+
*/
|
|
27
|
+
export type Optional<TBase, TOptionalKeys extends keyof TBase> = Pick<Partial<TBase>, TOptionalKeys> & Omit<TBase, TOptionalKeys>;
|
|
28
|
+
//#endregion
|
|
29
|
+
//# sourceMappingURL=optional.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { KeysOfType } from "./keys-of-type.js";
|
|
2
|
+
//#region src/types/pick-by-value.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Tipo utilitário que seleciona apenas as propriedades de um objeto cujos valores
|
|
5
|
+
* estendem um tipo específico. Complemento do `Pick` nativo, que seleciona por chave.
|
|
6
|
+
*
|
|
7
|
+
* @template TBase - Tipo base a ser filtrado.
|
|
8
|
+
* @template TValue - Tipo dos valores que serão mantidos.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
*
|
|
12
|
+
* type Usuario = {
|
|
13
|
+
* id: number;
|
|
14
|
+
* nome: string;
|
|
15
|
+
* email: string;
|
|
16
|
+
* ativo: boolean;
|
|
17
|
+
* idade: number;
|
|
18
|
+
* };
|
|
19
|
+
*
|
|
20
|
+
* type ApenasStrings = PickByValue<Usuario, string>;
|
|
21
|
+
*
|
|
22
|
+
* // Resultado:
|
|
23
|
+
* // {
|
|
24
|
+
* // nome: string;
|
|
25
|
+
* // email: string;
|
|
26
|
+
* // }
|
|
27
|
+
*/
|
|
28
|
+
export type PickByValue<TBase, TValue> = Pick<TBase, KeysOfType<TBase, TValue>>;
|
|
29
|
+
//#endregion
|
|
30
|
+
//# sourceMappingURL=pick-by-value.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/types/recompose.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Tipo utilitário que força a expansão e exibição completa de um tipo,
|
|
4
|
+
* tornando-o mais legível nas ferramentas de desenvolvimento.
|
|
5
|
+
*
|
|
6
|
+
* @template TOriginal - Tipo a ser expandido e tornado mais legível.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
*
|
|
10
|
+
* // Tipo complexo sem Recompose (pode aparecer colapsado em tooling)
|
|
11
|
+
* type UsuarioBase = { id: number; nome: string };
|
|
12
|
+
* type UsuarioComEmail = UsuarioBase & { email: string };
|
|
13
|
+
* type UsuarioCompleto = UsuarioComEmail & { ativo: boolean };
|
|
14
|
+
*
|
|
15
|
+
* // Sem Recompose, pode aparecer como:
|
|
16
|
+
* // UsuarioBase & UsuarioComEmail & { ativo: boolean }
|
|
17
|
+
* // ou
|
|
18
|
+
* // UsuarioBase & { email: string } & { ativo: boolean }
|
|
19
|
+
*
|
|
20
|
+
* // Com Recompose, fica expandido:
|
|
21
|
+
* type UsuarioExpandido = Recompose<UsuarioCompleto>;
|
|
22
|
+
* // Resultado: { id: number; nome: string; email: string; ativo: boolean }
|
|
23
|
+
*/
|
|
24
|
+
export type Recompose<TOriginal> = { [Key in keyof TOriginal]: TOriginal[Key]; } & {};
|
|
25
|
+
//#endregion
|
|
26
|
+
//# sourceMappingURL=recompose.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Recompose } from "./recompose.js";
|
|
2
|
+
//#region src/types/required-except.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Tipo utilitário que cria um novo tipo baseado no tipo base passado, tornando todas as propriedades
|
|
5
|
+
* obrigatórias, exceto as especificadas em OptionalKeys que permanecem opcionais.
|
|
6
|
+
*
|
|
7
|
+
* @template TBase - Tipo base de referência.
|
|
8
|
+
* @template OptionalKeys - Chaves de TBase que permanecerão opcionais.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
*
|
|
12
|
+
* type Usuario = {
|
|
13
|
+
* id: number;
|
|
14
|
+
* nome?: string;
|
|
15
|
+
* login?: string;
|
|
16
|
+
* idade?: number;
|
|
17
|
+
* };
|
|
18
|
+
*
|
|
19
|
+
* type UsuarioComIdadeOpcional = RequiredExcept<Usuario, 'idade'>;
|
|
20
|
+
*
|
|
21
|
+
* // Resultado:
|
|
22
|
+
* // {
|
|
23
|
+
* // id: number;
|
|
24
|
+
* // nome: string;
|
|
25
|
+
* // login: string;
|
|
26
|
+
* // idade?: number;
|
|
27
|
+
* // }
|
|
28
|
+
*/
|
|
29
|
+
export type RequiredExcept<TBase, OptionalKeys extends keyof TBase> = Recompose<Required<Omit<TBase, OptionalKeys>> & Partial<Pick<TBase, OptionalKeys>>>;
|
|
30
|
+
//#endregion
|
|
31
|
+
//# sourceMappingURL=required-except.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/types/serializable-value.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Tipo que representa um valor JSON válido, ou seja, que pode ser serializado
|
|
4
|
+
* de forma segura através de `JSON.stringify` e reconstruído com `JSON.parse`.
|
|
5
|
+
*
|
|
6
|
+
* Abrange funções e tipos primitivos suportados por JSON (string, número,
|
|
7
|
+
* booleano e null), além de arrays e objetos compostos por estes mesmos tipos.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
*
|
|
11
|
+
* const data: SerializableValue = {
|
|
12
|
+
* id: 1,
|
|
13
|
+
* nome: "Usuário",
|
|
14
|
+
* ativo: true,
|
|
15
|
+
* metadados: null,
|
|
16
|
+
* tags: ["typescript", "json"]
|
|
17
|
+
* };
|
|
18
|
+
*/
|
|
19
|
+
export type SerializableValue = string | number | boolean | null | SerializableValue[] | {
|
|
20
|
+
[key: string]: SerializableValue;
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
//# sourceMappingURL=serializable-value.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/types/strict-empty-object.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Tipo que representa um objeto estritamente vazio, sem qualquer propriedade.
|
|
4
|
+
* Útil para tipar cenários onde um objeto literalmente vazio é esperado,
|
|
5
|
+
* rejeitando qualquer tentativa de acesso ou atribuição de propriedades.
|
|
6
|
+
*
|
|
7
|
+
* Diferente de `{}` (que permite qualquer propriedade), este tipo garante
|
|
8
|
+
* em tempo de compilação que o objeto não contenha nem mesmo chaves opcionais.
|
|
9
|
+
*/
|
|
10
|
+
export type StrictEmptyObject = Record<string, never>;
|
|
11
|
+
//#endregion
|
|
12
|
+
//# sourceMappingURL=strict-empty-object.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/types/unknown.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Tipo genérico que representa qualquer valor desconhecido no TypeScript.
|
|
4
|
+
* Utilizado quando o tipo específico não pode ser determinado antecipadamente,
|
|
5
|
+
* mas diferenciado de `any` por preservar verificações de tipo mais seguras.
|
|
6
|
+
*/
|
|
7
|
+
export type UnknownType = unknown;
|
|
8
|
+
/**
|
|
9
|
+
* Tipo que representa um objeto genérico com chaves string e valores desconhecidos.
|
|
10
|
+
* Útil para modelar payloads ou estruturas dinâmicas onde as propriedades não são
|
|
11
|
+
* fixas ou não se conhece seus tipos em tempo de compilação.
|
|
12
|
+
*/
|
|
13
|
+
export type UnknownObject = Record<string, UnknownType>;
|
|
14
|
+
/**
|
|
15
|
+
* Tipo que representa um array genérico contendo elementos de tipo desconhecido.
|
|
16
|
+
* Pode ser utilizado para modelar listas ou coleções onde o tipo dos elementos
|
|
17
|
+
* não é conhecido ou pode variar.
|
|
18
|
+
*/
|
|
19
|
+
export type UnknownArray = UnknownType[];
|
|
20
|
+
/**
|
|
21
|
+
* Tipo que representa uma função genérica que recebe argumentos de tipo
|
|
22
|
+
* desconhecido e retorna um valor desconhecido.
|
|
23
|
+
*/
|
|
24
|
+
export type UnknownFunction = (...args: UnknownType[]) => UnknownType;
|
|
25
|
+
/**
|
|
26
|
+
* Tipo que representa um valor frouxamente tipado, podendo ser um primitivo,
|
|
27
|
+
* `null`, `undefined`, um objeto ou array com valores desconhecidos. Útil para modelar
|
|
28
|
+
* valores de origem incerta que ainda assim têm um conjunto limitado de formas possíveis,
|
|
29
|
+
* preservando verificações de tipo mais seguras que `AnyLooseValue`.
|
|
30
|
+
*/
|
|
31
|
+
export type UnknownLooseValue = string | number | boolean | UnknownObject | UnknownArray | null | undefined;
|
|
32
|
+
//#endregion
|
|
33
|
+
//# sourceMappingURL=unknown.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/types/value-of.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Tipo utilitário que extrai a união de todos os tipos de valores de um objeto.
|
|
4
|
+
*
|
|
5
|
+
* @template TBase - Tipo base cujos valores serão extraídos.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
*
|
|
9
|
+
* type Status = {
|
|
10
|
+
* ativo: 'ativo';
|
|
11
|
+
* inativo: 'inativo';
|
|
12
|
+
* pendente: 'pendente';
|
|
13
|
+
* };
|
|
14
|
+
*
|
|
15
|
+
* type ValorStatus = ValueOf<Status>;
|
|
16
|
+
* // Resultado: 'ativo' | 'inativo' | 'pendente'
|
|
17
|
+
*/
|
|
18
|
+
export type ValueOf<TBase> = TBase[keyof TBase];
|
|
19
|
+
//#endregion
|
|
20
|
+
//# sourceMappingURL=value-of.d.ts.map
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/utils/compose-event-handlers.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Combina múltiplos callbacks de eventos em um único handler, executando-os em sequência
|
|
4
|
+
* com os mesmos argumentos. Handlers `undefined` são ignorados silenciosamente.
|
|
5
|
+
*
|
|
6
|
+
* Projetado para uso em eventos de componentes, onde é comum precisar chamar um handler
|
|
7
|
+
* vindo de props junto com um handler interno — sem que um sobrescreva o outro.
|
|
8
|
+
*
|
|
9
|
+
* Os argumentos (`Args`) são inferidos dos callbacks ou do contexto de uso (ex: prop de evento do
|
|
10
|
+
* componente), o que permite escrever callbacks inline sem anotar os parâmetros manualmente.
|
|
11
|
+
*
|
|
12
|
+
* @template Args - Argumentos do handler de evento.
|
|
13
|
+
* @param callbacks - Um ou mais callbacks a serem executados em sequência. Aceita `undefined`.
|
|
14
|
+
* @returns Um único handler que chama todos os callbacks fornecidos na ordem recebida.
|
|
15
|
+
*/
|
|
16
|
+
export declare const composeEventHandlers: <Args extends unknown[]>(...callbacks: Array<((...args: Args) => void) | undefined>) => (...args: Args) => void;
|
|
17
|
+
//#endregion
|
|
18
|
+
//# sourceMappingURL=compose-event-handlers.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/utils/compose-event-handlers.ts
|
|
2
|
+
/**
|
|
3
|
+
* Combina múltiplos callbacks de eventos em um único handler, executando-os em sequência
|
|
4
|
+
* com os mesmos argumentos. Handlers `undefined` são ignorados silenciosamente.
|
|
5
|
+
*
|
|
6
|
+
* Projetado para uso em eventos de componentes, onde é comum precisar chamar um handler
|
|
7
|
+
* vindo de props junto com um handler interno — sem que um sobrescreva o outro.
|
|
8
|
+
*
|
|
9
|
+
* Os argumentos (`Args`) são inferidos dos callbacks ou do contexto de uso (ex: prop de evento do
|
|
10
|
+
* componente), o que permite escrever callbacks inline sem anotar os parâmetros manualmente.
|
|
11
|
+
*
|
|
12
|
+
* @template Args - Argumentos do handler de evento.
|
|
13
|
+
* @param callbacks - Um ou mais callbacks a serem executados em sequência. Aceita `undefined`.
|
|
14
|
+
* @returns Um único handler que chama todos os callbacks fornecidos na ordem recebida.
|
|
15
|
+
*/
|
|
16
|
+
const composeEventHandlers = (...callbacks) => (...args) => {
|
|
17
|
+
for (const handler of callbacks) if (handler) handler(...args);
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { composeEventHandlers };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=compose-event-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-event-handlers.js","names":[],"sources":["../../src/utils/compose-event-handlers.ts"],"sourcesContent":["/**\n * Combina múltiplos callbacks de eventos em um único handler, executando-os em sequência\n * com os mesmos argumentos. Handlers `undefined` são ignorados silenciosamente.\n *\n * Projetado para uso em eventos de componentes, onde é comum precisar chamar um handler\n * vindo de props junto com um handler interno — sem que um sobrescreva o outro.\n *\n * Os argumentos (`Args`) são inferidos dos callbacks ou do contexto de uso (ex: prop de evento do\n * componente), o que permite escrever callbacks inline sem anotar os parâmetros manualmente.\n *\n * @template Args - Argumentos do handler de evento.\n * @param callbacks - Um ou mais callbacks a serem executados em sequência. Aceita `undefined`.\n * @returns Um único handler que chama todos os callbacks fornecidos na ordem recebida.\n */\nexport const composeEventHandlers =\n <Args extends unknown[]>(\n ...callbacks: Array<((...args: Args) => void) | undefined>\n ) =>\n (...args: Args): void => {\n for (const handler of callbacks) {\n // Handlers undefined são ignorados para permitir passar props opcionais diretamente\n if (handler) {\n handler(...args);\n }\n }\n };\n"],"mappings":";;;;;;;;;;;;;;;AAcA,MAAa,wBAET,GAAG,eAEJ,GAAG,SAAqB;CACvB,KAAK,MAAM,WAAW,WAEpB,IAAI,SACF,QAAQ,GAAG,IAAI;AAGrB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/utils/create-split-props.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extrai as chaves de `Target` que ainda não foram cobertas por `ProvidedKeys`.
|
|
4
|
+
*
|
|
5
|
+
* @template Target - Objeto de referência cujas chaves são checadas.
|
|
6
|
+
* @template ProvidedKeys - Subconjunto de chaves de `Target` já fornecido.
|
|
7
|
+
*/
|
|
8
|
+
type MissingKeys<Target, ProvidedKeys extends keyof Target> = Exclude<keyof Target, ProvidedKeys>;
|
|
9
|
+
/**
|
|
10
|
+
* Checagem de exaustividade em tempo de compilação: garante que `ProvidedKeys`
|
|
11
|
+
* cubra todas as chaves de `Target`. Quando falta alguma chave, o tipo vira uma
|
|
12
|
+
* mensagem de erro literal, fazendo o TypeScript reclamar no parâmetro `keys`
|
|
13
|
+
* de `createSplitProps`.
|
|
14
|
+
*
|
|
15
|
+
* @template ProvidedKeys - Lista de chaves de `Target` fornecida pelo chamador.
|
|
16
|
+
* @template Target - Objeto de referência cujas chaves devem ser totalmente cobertas.
|
|
17
|
+
*/
|
|
18
|
+
type EnsureAllKeysProvided<ProvidedKeys extends (keyof Target)[], Target> = keyof Target extends ProvidedKeys[number] ? unknown : `Missing required keys: ${MissingKeys<Target, ProvidedKeys[number]> & string}`;
|
|
19
|
+
/**
|
|
20
|
+
* Cria uma função que separa um objeto de props em duas partes:
|
|
21
|
+
* - um objeto `Target`, contendo apenas as chaves informadas em `keys`;
|
|
22
|
+
* - o restante das props, tipado como `Omit<Props, Keys>`.
|
|
23
|
+
*
|
|
24
|
+
* `EnsureAllKeysProvided` obriga a lista `keys` a cobrir todas as chaves
|
|
25
|
+
* de `Target`, evitando esquecer alguma propriedade na divisão.
|
|
26
|
+
*
|
|
27
|
+
* @template Target - Forma do objeto que define quais chaves serão extraídas.
|
|
28
|
+
* @returns Função configurada para `Target` que recebe `props` e `keys` e devolve a divisão.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* type ButtonProps = { label: string; onClick: () => void }
|
|
33
|
+
* const [buttonProps, restProps] = createSplitProps<ButtonProps>()(props, ['label', 'onClick'])
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare const createSplitProps: <Target>() => <Keys extends (keyof Target)[], Props extends Target = Target>(props: Props, keys: Keys & EnsureAllKeysProvided<Keys, Target>) => [Target, Omit<Props, Extract<Keys[number], string>>];
|
|
37
|
+
//#endregion
|
|
38
|
+
//# sourceMappingURL=create-split-props.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/utils/create-split-props.ts
|
|
2
|
+
/**
|
|
3
|
+
* Cria uma função que separa um objeto de props em duas partes:
|
|
4
|
+
* - um objeto `Target`, contendo apenas as chaves informadas em `keys`;
|
|
5
|
+
* - o restante das props, tipado como `Omit<Props, Keys>`.
|
|
6
|
+
*
|
|
7
|
+
* `EnsureAllKeysProvided` obriga a lista `keys` a cobrir todas as chaves
|
|
8
|
+
* de `Target`, evitando esquecer alguma propriedade na divisão.
|
|
9
|
+
*
|
|
10
|
+
* @template Target - Forma do objeto que define quais chaves serão extraídas.
|
|
11
|
+
* @returns Função configurada para `Target` que recebe `props` e `keys` e devolve a divisão.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* type ButtonProps = { label: string; onClick: () => void }
|
|
16
|
+
* const [buttonProps, restProps] = createSplitProps<ButtonProps>()(props, ['label', 'onClick'])
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
const createSplitProps = () => (props, keys) => {
|
|
20
|
+
/**
|
|
21
|
+
* Os casts ficam porque o TypeScript não prova que copiar as chaves de uma lista monta um
|
|
22
|
+
* `Target` e deixa um `Omit<Props, KeyName>`: o objeto nasce vazio e cresce chave a chave. A
|
|
23
|
+
* garantia vem do `EnsureAllKeysProvided`, que obriga a lista a cobrir todo o `Target`.
|
|
24
|
+
*/
|
|
25
|
+
return keys.reduce((splitResult, keyName) => {
|
|
26
|
+
const [pickedProps, remainingProps] = splitResult;
|
|
27
|
+
const typedKey = keyName;
|
|
28
|
+
if (remainingProps[typedKey] !== void 0) pickedProps[typedKey] = remainingProps[typedKey];
|
|
29
|
+
delete remainingProps[typedKey];
|
|
30
|
+
return splitResult;
|
|
31
|
+
}, [{}, { ...props }]);
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { createSplitProps };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=create-split-props.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-split-props.js","names":[],"sources":["../../src/utils/create-split-props.ts"],"sourcesContent":["/**\n * Extrai as chaves de `Target` que ainda não foram cobertas por `ProvidedKeys`.\n *\n * @template Target - Objeto de referência cujas chaves são checadas.\n * @template ProvidedKeys - Subconjunto de chaves de `Target` já fornecido.\n */\ntype MissingKeys<Target, ProvidedKeys extends keyof Target> = Exclude<\n keyof Target,\n ProvidedKeys\n>;\n\n/**\n * Checagem de exaustividade em tempo de compilação: garante que `ProvidedKeys`\n * cubra todas as chaves de `Target`. Quando falta alguma chave, o tipo vira uma\n * mensagem de erro literal, fazendo o TypeScript reclamar no parâmetro `keys`\n * de `createSplitProps`.\n *\n * @template ProvidedKeys - Lista de chaves de `Target` fornecida pelo chamador.\n * @template Target - Objeto de referência cujas chaves devem ser totalmente cobertas.\n */\ntype EnsureAllKeysProvided<\n ProvidedKeys extends (keyof Target)[],\n Target,\n> = keyof Target extends ProvidedKeys[number]\n ? unknown\n : `Missing required keys: ${MissingKeys<Target, ProvidedKeys[number]> & string}`;\n\n/**\n * Cria uma função que separa um objeto de props em duas partes:\n * - um objeto `Target`, contendo apenas as chaves informadas em `keys`;\n * - o restante das props, tipado como `Omit<Props, Keys>`.\n *\n * `EnsureAllKeysProvided` obriga a lista `keys` a cobrir todas as chaves\n * de `Target`, evitando esquecer alguma propriedade na divisão.\n *\n * @template Target - Forma do objeto que define quais chaves serão extraídas.\n * @returns Função configurada para `Target` que recebe `props` e `keys` e devolve a divisão.\n *\n * @example\n * ```ts\n * type ButtonProps = { label: string; onClick: () => void }\n * const [buttonProps, restProps] = createSplitProps<ButtonProps>()(props, ['label', 'onClick'])\n * ```\n */\nexport const createSplitProps =\n <Target>() =>\n /**\n * @template Keys - Tupla das chaves de `Target` a extrair, deve cobri-lo por completo.\n * @template Props - Tipo do objeto de entrada, deve estender `Target`.\n * @param props - Objeto de props a ser dividido.\n * @param keys - Lista de chaves de `Target` a extrair para o primeiro item do retorno.\n * @returns Tupla `[pickedProps, remainingProps]` com as chaves extraídas e o restante.\n */\n <Keys extends (keyof Target)[], Props extends Target = Target>(\n props: Props,\n keys: Keys & EnsureAllKeysProvided<Keys, Target>,\n ) => {\n type KeyName = Extract<Keys[number], string>;\n\n /**\n * Os casts ficam porque o TypeScript não prova que copiar as chaves de uma lista monta um\n * `Target` e deixa um `Omit<Props, KeyName>`: o objeto nasce vazio e cresce chave a chave. A\n * garantia vem do `EnsureAllKeysProvided`, que obriga a lista a cobrir todo o `Target`.\n */\n // biome-ignore lint/nursery/noUnsafeTypeAssertion: ver o comentário acima do `return`\n return (keys as string[]).reduce<[Target, Omit<Props, KeyName>]>(\n (splitResult, keyName) => {\n const [pickedProps, remainingProps] = splitResult;\n\n // biome-ignore lint/nursery/noUnsafeTypeAssertion: ver o comentário acima do `return`\n const typedKey = keyName as keyof Target & keyof typeof remainingProps;\n\n if (remainingProps[typedKey] !== undefined) {\n pickedProps[typedKey] = remainingProps[typedKey];\n }\n\n delete remainingProps[typedKey];\n\n return splitResult;\n },\n // biome-ignore lint/nursery/noUnsafeTypeAssertion: ver o comentário acima do `return`\n [{} as Target, { ...props }],\n );\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4CA,MAAa,0BAUT,OACA,SACG;;;;;;CASH,OAAQ,KAAkB,QACvB,aAAa,YAAY;EACxB,MAAM,CAAC,aAAa,kBAAkB;EAGtC,MAAM,WAAW;EAEjB,IAAI,eAAe,cAAc,KAAA,GAC/B,YAAY,YAAY,eAAe;EAGzC,OAAO,eAAe;EAEtB,OAAO;CACT,GAEA,CAAC,CAAC,GAAa,EAAE,GAAG,MAAM,CAAC,CAC7B;AACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/utils/get-initials.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Iniciais de um nome, em maiúsculas: a primeira letra do primeiro e a do último nome, ou só a do
|
|
4
|
+
* primeiro quando há um nome só. Um nome vazio devolve string vazia.
|
|
5
|
+
*
|
|
6
|
+
* A primeira letra é lida por caractere, não por unidade de UTF-16: um nome que começa com emoji
|
|
7
|
+
* ou outro caractere fora do plano básico não sai cortado ao meio.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* getInitials('Lucas Bernardo da Silva') // 'LS'
|
|
11
|
+
* getInitials('lucas') // 'L'
|
|
12
|
+
*/
|
|
13
|
+
export declare const getInitials: (name: string) => string;
|
|
14
|
+
//#endregion
|
|
15
|
+
//# sourceMappingURL=get-initials.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/utils/get-initials.ts
|
|
2
|
+
const WORD_SEPARATOR = /\s+/;
|
|
3
|
+
/**
|
|
4
|
+
* Iniciais de um nome, em maiúsculas: a primeira letra do primeiro e a do último nome, ou só a do
|
|
5
|
+
* primeiro quando há um nome só. Um nome vazio devolve string vazia.
|
|
6
|
+
*
|
|
7
|
+
* A primeira letra é lida por caractere, não por unidade de UTF-16: um nome que começa com emoji
|
|
8
|
+
* ou outro caractere fora do plano básico não sai cortado ao meio.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* getInitials('Lucas Bernardo da Silva') // 'LS'
|
|
12
|
+
* getInitials('lucas') // 'L'
|
|
13
|
+
*/
|
|
14
|
+
const getInitials = (name) => {
|
|
15
|
+
const words = name.trim().split(WORD_SEPARATOR).filter(Boolean);
|
|
16
|
+
return [words.at(0), words.length > 1 ? words.at(-1) : void 0].map((word) => word === void 0 ? "" : Array.from(word).at(0) ?? "").join("").toUpperCase();
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { getInitials };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=get-initials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-initials.js","names":[],"sources":["../../src/utils/get-initials.ts"],"sourcesContent":["const WORD_SEPARATOR = /\\s+/;\n\n/**\n * Iniciais de um nome, em maiúsculas: a primeira letra do primeiro e a do último nome, ou só a do\n * primeiro quando há um nome só. Um nome vazio devolve string vazia.\n *\n * A primeira letra é lida por caractere, não por unidade de UTF-16: um nome que começa com emoji\n * ou outro caractere fora do plano básico não sai cortado ao meio.\n *\n * @example\n * getInitials('Lucas Bernardo da Silva') // 'LS'\n * getInitials('lucas') // 'L'\n */\nexport const getInitials = (name: string) => {\n const words = name.trim().split(WORD_SEPARATOR).filter(Boolean);\n\n const firstWord = words.at(0);\n const lastWord = words.length > 1 ? words.at(-1) : undefined;\n\n return [firstWord, lastWord]\n .map((word) => (word === undefined ? '' : (Array.from(word).at(0) ?? '')))\n .join('')\n .toUpperCase();\n};\n"],"mappings":";AAAA,MAAM,iBAAiB;;;;;;;;;;;;AAavB,MAAa,eAAe,SAAiB;CAC3C,MAAM,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,cAAc,CAAC,CAAC,OAAO,OAAO;CAK9D,OAAO,CAHW,MAAM,GAAG,CAGX,GAFC,MAAM,SAAS,IAAI,MAAM,GAAG,EAAE,IAAI,KAAA,CAExB,CAAC,CACzB,KAAK,SAAU,SAAS,KAAA,IAAY,KAAM,MAAM,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,EAAI,CAAC,CACzE,KAAK,EAAE,CAAC,CACR,YAAY;AACjB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { composeEventHandlers } from "./compose-event-handlers.js";
|
|
2
|
+
import { createSplitProps } from "./create-split-props.js";
|
|
3
|
+
import { getInitials } from "./get-initials.js";
|
|
4
|
+
import { isDeepEqual } from "./is-deep-equal.js";
|
|
5
|
+
import { isNotNullish } from "./is-not-nullish.js";
|
|
6
|
+
import { mergeBooleansAnd, mergeBooleansOr } from "./merge-booleans.js";
|
|
7
|
+
import { PascalCase, toPascalCase } from "./to-pascal-case.js";
|
|
8
|
+
export { PascalCase, composeEventHandlers, createSplitProps, getInitials, isDeepEqual, isNotNullish, mergeBooleansAnd, mergeBooleansOr, toPascalCase };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { composeEventHandlers } from "./compose-event-handlers.js";
|
|
2
|
+
import { createSplitProps } from "./create-split-props.js";
|
|
3
|
+
import { getInitials } from "./get-initials.js";
|
|
4
|
+
import { isDeepEqual } from "./is-deep-equal.js";
|
|
5
|
+
import { isNotNullish } from "./is-not-nullish.js";
|
|
6
|
+
import { mergeBooleansAnd, mergeBooleansOr } from "./merge-booleans.js";
|
|
7
|
+
import { toPascalCase } from "./to-pascal-case.js";
|
|
8
|
+
export { composeEventHandlers, createSplitProps, getInitials, isDeepEqual, isNotNullish, mergeBooleansAnd, mergeBooleansOr, toPascalCase };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/utils/is-deep-equal.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Compara dois valores por igualdade profunda (deep equality).
|
|
4
|
+
*
|
|
5
|
+
* Suporta todos os tipos nativos do JavaScript:
|
|
6
|
+
* primitivos, `Date`, `RegExp`, `Array`, `Set`, `Map`,
|
|
7
|
+
* `ArrayBuffer`, `DataView`, TypedArrays e objetos genéricos.
|
|
8
|
+
*
|
|
9
|
+
* **Atenção:** não suporta referências circulares — causam stack overflow.
|
|
10
|
+
*
|
|
11
|
+
* @param valueA - Primeiro valor a ser comparado
|
|
12
|
+
* @param valueB - Segundo valor a ser comparado
|
|
13
|
+
* @returns `true` se os valores forem profundamente iguais, `false` caso contrário
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* isDeepEqual({ a: 1 }, { a: 1 }) // true
|
|
17
|
+
* isDeepEqual([1, [2]], [1, [2]]) // true
|
|
18
|
+
* isDeepEqual(NaN, NaN) // true
|
|
19
|
+
* isDeepEqual(new Date('2024'), new Date('2024')) // true
|
|
20
|
+
* isDeepEqual({ a: 1 }, { a: 2 }) // false
|
|
21
|
+
*/
|
|
22
|
+
export declare const isDeepEqual: (valueA: unknown, valueB: unknown) => boolean;
|
|
23
|
+
//#endregion
|
|
24
|
+
//# sourceMappingURL=is-deep-equal.d.ts.map
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
//#region src/utils/is-deep-equal.ts
|
|
2
|
+
/**
|
|
3
|
+
* Compara dois valores por igualdade profunda (deep equality).
|
|
4
|
+
*
|
|
5
|
+
* Suporta todos os tipos nativos do JavaScript:
|
|
6
|
+
* primitivos, `Date`, `RegExp`, `Array`, `Set`, `Map`,
|
|
7
|
+
* `ArrayBuffer`, `DataView`, TypedArrays e objetos genéricos.
|
|
8
|
+
*
|
|
9
|
+
* **Atenção:** não suporta referências circulares — causam stack overflow.
|
|
10
|
+
*
|
|
11
|
+
* @param valueA - Primeiro valor a ser comparado
|
|
12
|
+
* @param valueB - Segundo valor a ser comparado
|
|
13
|
+
* @returns `true` se os valores forem profundamente iguais, `false` caso contrário
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* isDeepEqual({ a: 1 }, { a: 1 }) // true
|
|
17
|
+
* isDeepEqual([1, [2]], [1, [2]]) // true
|
|
18
|
+
* isDeepEqual(NaN, NaN) // true
|
|
19
|
+
* isDeepEqual(new Date('2024'), new Date('2024')) // true
|
|
20
|
+
* isDeepEqual({ a: 1 }, { a: 2 }) // false
|
|
21
|
+
*/
|
|
22
|
+
const isDeepEqual = (valueA, valueB) => {
|
|
23
|
+
if (valueA === valueB) return true;
|
|
24
|
+
/**
|
|
25
|
+
* Fora de dois objetos, só sobra o `NaN`, o único valor diferente de si mesmo. `null` entra aqui
|
|
26
|
+
* porque `typeof null` é `'object'`: sem a checagem, ele chegaria ao `.constructor`.
|
|
27
|
+
*/
|
|
28
|
+
if (typeof valueA !== "object" || typeof valueB !== "object" || valueA === null || valueB === null) return valueA !== valueA && valueB !== valueB;
|
|
29
|
+
/**
|
|
30
|
+
* O mesmo construtor separa instâncias de classes diferentes com as mesmas chaves, e um Array de
|
|
31
|
+
* um objeto com índices. Os `instanceof` abaixo só estreitam o tipo para o TypeScript.
|
|
32
|
+
*/
|
|
33
|
+
if (valueA.constructor !== valueB.constructor) return false;
|
|
34
|
+
if (valueA instanceof Date && valueB instanceof Date) return valueA.getTime() === valueB.getTime();
|
|
35
|
+
if (valueA instanceof RegExp && valueB instanceof RegExp) return valueA.toString() === valueB.toString();
|
|
36
|
+
/** Array: só `length` e os itens por índice, sem as outras propriedades próprias. */
|
|
37
|
+
if (Array.isArray(valueA) && Array.isArray(valueB)) {
|
|
38
|
+
const arrayA = valueA;
|
|
39
|
+
const arrayB = valueB;
|
|
40
|
+
if (arrayA.length !== arrayB.length) return false;
|
|
41
|
+
/** Laço por índice, não `every`: o `every` pula os buracos de um array esparso. */
|
|
42
|
+
for (let index = 0; index < arrayA.length; index++) if (!isDeepEqual(arrayA[index], arrayB[index])) return false;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Set e Map: itens e chaves que são objetos precisam de busca por igualdade profunda, porque o
|
|
47
|
+
* `has` só acha a mesma referência.
|
|
48
|
+
*/
|
|
49
|
+
if (valueA instanceof Set && valueB instanceof Set) {
|
|
50
|
+
const setA = valueA;
|
|
51
|
+
const setB = valueB;
|
|
52
|
+
if (setA.size !== setB.size) return false;
|
|
53
|
+
for (const item of setA) {
|
|
54
|
+
const resolvedItem = item && typeof item === "object" ? findDeepEqualKey(setB, item) : item;
|
|
55
|
+
if (resolvedItem === void 0 || !setB.has(resolvedItem)) return false;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (valueA instanceof Map && valueB instanceof Map) {
|
|
60
|
+
const mapA = valueA;
|
|
61
|
+
const mapB = valueB;
|
|
62
|
+
if (mapA.size !== mapB.size) return false;
|
|
63
|
+
for (const [keyA, entryValueA] of mapA) {
|
|
64
|
+
const resolvedKey = keyA && typeof keyA === "object" ? findDeepEqualKey(mapB, keyA) : keyA;
|
|
65
|
+
if (resolvedKey === void 0) return false;
|
|
66
|
+
if (!isDeepEqual(entryValueA, mapB.get(resolvedKey))) return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* ArrayBuffer, DataView e TypedArrays comparam byte a byte. Num array de ponto flutuante, `0` e
|
|
72
|
+
* `-0` têm bytes diferentes e contam como diferentes.
|
|
73
|
+
*/
|
|
74
|
+
if (valueA instanceof ArrayBuffer && valueB instanceof ArrayBuffer) return areBytesEqual(new Uint8Array(valueA), new Uint8Array(valueB));
|
|
75
|
+
if (ArrayBuffer.isView(valueA) && ArrayBuffer.isView(valueB)) return areBytesEqual(toBytes(valueA), toBytes(valueB));
|
|
76
|
+
/**
|
|
77
|
+
* Objetos genéricos (literais, instâncias de classe, `Object.create(null)`): as chaves próprias
|
|
78
|
+
* enumeráveis, em qualquer ordem. WeakMap e WeakSet não têm chaves visíveis e sempre saem iguais.
|
|
79
|
+
*/
|
|
80
|
+
const entriesA = Object.entries(valueA);
|
|
81
|
+
if (entriesA.length !== Object.keys(valueB).length) return false;
|
|
82
|
+
const entriesB = new Map(Object.entries(valueB));
|
|
83
|
+
return entriesA.every(([key, entryValueA]) => entriesB.has(key) && isDeepEqual(entryValueA, entriesB.get(key)));
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Os bytes que uma view (TypedArray ou DataView) enxerga no buffer dela.
|
|
87
|
+
*/
|
|
88
|
+
const toBytes = (view) => new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
89
|
+
/**
|
|
90
|
+
* Compara dois blocos de bytes, posição por posição.
|
|
91
|
+
*/
|
|
92
|
+
const areBytesEqual = (bytesA, bytesB) => bytesA.length === bytesB.length && bytesA.every((byte, index) => byte === bytesB[index]);
|
|
93
|
+
/**
|
|
94
|
+
* Busca, dentro de um iterável (Set ou Map), uma chave que seja
|
|
95
|
+
* profundamente igual ao alvo informado.
|
|
96
|
+
*
|
|
97
|
+
* Necessário para comparar chaves de objetos dentro de Sets/Maps,
|
|
98
|
+
* já que a igualdade referencial nativa não é suficiente nesses casos.
|
|
99
|
+
*
|
|
100
|
+
* @param iterable - O Set ou Map cujas chaves serão percorridas
|
|
101
|
+
* @param target - O valor alvo a ser encontrado por igualdade profunda
|
|
102
|
+
* @returns A chave encontrada ou `undefined` caso não exista
|
|
103
|
+
*/
|
|
104
|
+
const findDeepEqualKey = (iterable, target) => {
|
|
105
|
+
for (const key of iterable.keys()) if (isDeepEqual(key, target)) return key;
|
|
106
|
+
};
|
|
107
|
+
//#endregion
|
|
108
|
+
export { isDeepEqual };
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=is-deep-equal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-deep-equal.js","names":[],"sources":["../../src/utils/is-deep-equal.ts"],"sourcesContent":["/**\n * Compara dois valores por igualdade profunda (deep equality).\n *\n * Suporta todos os tipos nativos do JavaScript:\n * primitivos, `Date`, `RegExp`, `Array`, `Set`, `Map`,\n * `ArrayBuffer`, `DataView`, TypedArrays e objetos genéricos.\n *\n * **Atenção:** não suporta referências circulares — causam stack overflow.\n *\n * @param valueA - Primeiro valor a ser comparado\n * @param valueB - Segundo valor a ser comparado\n * @returns `true` se os valores forem profundamente iguais, `false` caso contrário\n *\n * @example\n * isDeepEqual({ a: 1 }, { a: 1 }) // true\n * isDeepEqual([1, [2]], [1, [2]]) // true\n * isDeepEqual(NaN, NaN) // true\n * isDeepEqual(new Date('2024'), new Date('2024')) // true\n * isDeepEqual({ a: 1 }, { a: 2 }) // false\n */\nexport const isDeepEqual = (valueA: unknown, valueB: unknown): boolean => {\n if (valueA === valueB) {\n return true;\n }\n\n /**\n * Fora de dois objetos, só sobra o `NaN`, o único valor diferente de si mesmo. `null` entra aqui\n * porque `typeof null` é `'object'`: sem a checagem, ele chegaria ao `.constructor`.\n */\n if (\n typeof valueA !== 'object' ||\n typeof valueB !== 'object' ||\n valueA === null ||\n valueB === null\n ) {\n // biome-ignore lint/suspicious/noSelfCompare: comparação intencional para detectar NaN\n return valueA !== valueA && valueB !== valueB;\n }\n\n /**\n * O mesmo construtor separa instâncias de classes diferentes com as mesmas chaves, e um Array de\n * um objeto com índices. Os `instanceof` abaixo só estreitam o tipo para o TypeScript.\n */\n if (valueA.constructor !== valueB.constructor) {\n return false;\n }\n\n if (valueA instanceof Date && valueB instanceof Date) {\n return valueA.getTime() === valueB.getTime();\n }\n\n if (valueA instanceof RegExp && valueB instanceof RegExp) {\n return valueA.toString() === valueB.toString();\n }\n\n /** Array: só `length` e os itens por índice, sem as outras propriedades próprias. */\n if (Array.isArray(valueA) && Array.isArray(valueB)) {\n const arrayA: readonly unknown[] = valueA;\n const arrayB: readonly unknown[] = valueB;\n\n if (arrayA.length !== arrayB.length) {\n return false;\n }\n\n /** Laço por índice, não `every`: o `every` pula os buracos de um array esparso. */\n for (let index = 0; index < arrayA.length; index++) {\n if (!isDeepEqual(arrayA[index], arrayB[index])) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Set e Map: itens e chaves que são objetos precisam de busca por igualdade profunda, porque o\n * `has` só acha a mesma referência.\n */\n if (valueA instanceof Set && valueB instanceof Set) {\n const setA: ReadonlySet<unknown> = valueA;\n const setB: ReadonlySet<unknown> = valueB;\n\n if (setA.size !== setB.size) {\n return false;\n }\n\n for (const item of setA) {\n const resolvedItem =\n item && typeof item === 'object' ? findDeepEqualKey(setB, item) : item;\n\n if (resolvedItem === undefined || !setB.has(resolvedItem)) {\n return false;\n }\n }\n\n return true;\n }\n\n if (valueA instanceof Map && valueB instanceof Map) {\n const mapA: ReadonlyMap<unknown, unknown> = valueA;\n const mapB: ReadonlyMap<unknown, unknown> = valueB;\n\n if (mapA.size !== mapB.size) {\n return false;\n }\n\n for (const [keyA, entryValueA] of mapA) {\n const resolvedKey =\n keyA && typeof keyA === 'object' ? findDeepEqualKey(mapB, keyA) : keyA;\n\n if (resolvedKey === undefined) {\n return false;\n }\n\n if (!isDeepEqual(entryValueA, mapB.get(resolvedKey))) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * ArrayBuffer, DataView e TypedArrays comparam byte a byte. Num array de ponto flutuante, `0` e\n * `-0` têm bytes diferentes e contam como diferentes.\n */\n if (valueA instanceof ArrayBuffer && valueB instanceof ArrayBuffer) {\n return areBytesEqual(new Uint8Array(valueA), new Uint8Array(valueB));\n }\n\n if (ArrayBuffer.isView(valueA) && ArrayBuffer.isView(valueB)) {\n return areBytesEqual(toBytes(valueA), toBytes(valueB));\n }\n\n /**\n * Objetos genéricos (literais, instâncias de classe, `Object.create(null)`): as chaves próprias\n * enumeráveis, em qualquer ordem. WeakMap e WeakSet não têm chaves visíveis e sempre saem iguais.\n */\n const entriesA: [string, unknown][] = Object.entries(valueA);\n\n if (entriesA.length !== Object.keys(valueB).length) {\n return false;\n }\n\n const entriesB = new Map<string, unknown>(Object.entries(valueB));\n\n return entriesA.every(\n ([key, entryValueA]) =>\n entriesB.has(key) && isDeepEqual(entryValueA, entriesB.get(key)),\n );\n};\n\n/**\n * Os bytes que uma view (TypedArray ou DataView) enxerga no buffer dela.\n */\nconst toBytes = (view: ArrayBufferView): Uint8Array =>\n new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n\n/**\n * Compara dois blocos de bytes, posição por posição.\n */\nconst areBytesEqual = (bytesA: Uint8Array, bytesB: Uint8Array): boolean =>\n bytesA.length === bytesB.length &&\n bytesA.every((byte, index) => byte === bytesB[index]);\n\n/**\n * Busca, dentro de um iterável (Set ou Map), uma chave que seja\n * profundamente igual ao alvo informado.\n *\n * Necessário para comparar chaves de objetos dentro de Sets/Maps,\n * já que a igualdade referencial nativa não é suficiente nesses casos.\n *\n * @param iterable - O Set ou Map cujas chaves serão percorridas\n * @param target - O valor alvo a ser encontrado por igualdade profunda\n * @returns A chave encontrada ou `undefined` caso não exista\n */\nconst findDeepEqualKey = (\n iterable: ReadonlySet<unknown> | ReadonlyMap<unknown, unknown>,\n target: unknown,\n): unknown => {\n for (const key of iterable.keys()) {\n if (isDeepEqual(key, target)) {\n return key;\n }\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,eAAe,QAAiB,WAA6B;CACxE,IAAI,WAAW,QACb,OAAO;;;;;CAOT,IACE,OAAO,WAAW,YAClB,OAAO,WAAW,YAClB,WAAW,QACX,WAAW,MAGX,OAAO,WAAW,UAAU,WAAW;;;;;CAOzC,IAAI,OAAO,gBAAgB,OAAO,aAChC,OAAO;CAGT,IAAI,kBAAkB,QAAQ,kBAAkB,MAC9C,OAAO,OAAO,QAAQ,MAAM,OAAO,QAAQ;CAG7C,IAAI,kBAAkB,UAAU,kBAAkB,QAChD,OAAO,OAAO,SAAS,MAAM,OAAO,SAAS;;CAI/C,IAAI,MAAM,QAAQ,MAAM,KAAK,MAAM,QAAQ,MAAM,GAAG;EAClD,MAAM,SAA6B;EACnC,MAAM,SAA6B;EAEnC,IAAI,OAAO,WAAW,OAAO,QAC3B,OAAO;;EAIT,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SACzC,IAAI,CAAC,YAAY,OAAO,QAAQ,OAAO,MAAM,GAC3C,OAAO;EAIX,OAAO;CACT;;;;;CAMA,IAAI,kBAAkB,OAAO,kBAAkB,KAAK;EAClD,MAAM,OAA6B;EACnC,MAAM,OAA6B;EAEnC,IAAI,KAAK,SAAS,KAAK,MACrB,OAAO;EAGT,KAAK,MAAM,QAAQ,MAAM;GACvB,MAAM,eACJ,QAAQ,OAAO,SAAS,WAAW,iBAAiB,MAAM,IAAI,IAAI;GAEpE,IAAI,iBAAiB,KAAA,KAAa,CAAC,KAAK,IAAI,YAAY,GACtD,OAAO;EAEX;EAEA,OAAO;CACT;CAEA,IAAI,kBAAkB,OAAO,kBAAkB,KAAK;EAClD,MAAM,OAAsC;EAC5C,MAAM,OAAsC;EAE5C,IAAI,KAAK,SAAS,KAAK,MACrB,OAAO;EAGT,KAAK,MAAM,CAAC,MAAM,gBAAgB,MAAM;GACtC,MAAM,cACJ,QAAQ,OAAO,SAAS,WAAW,iBAAiB,MAAM,IAAI,IAAI;GAEpE,IAAI,gBAAgB,KAAA,GAClB,OAAO;GAGT,IAAI,CAAC,YAAY,aAAa,KAAK,IAAI,WAAW,CAAC,GACjD,OAAO;EAEX;EAEA,OAAO;CACT;;;;;CAMA,IAAI,kBAAkB,eAAe,kBAAkB,aACrD,OAAO,cAAc,IAAI,WAAW,MAAM,GAAG,IAAI,WAAW,MAAM,CAAC;CAGrE,IAAI,YAAY,OAAO,MAAM,KAAK,YAAY,OAAO,MAAM,GACzD,OAAO,cAAc,QAAQ,MAAM,GAAG,QAAQ,MAAM,CAAC;;;;;CAOvD,MAAM,WAAgC,OAAO,QAAQ,MAAM;CAE3D,IAAI,SAAS,WAAW,OAAO,KAAK,MAAM,CAAC,CAAC,QAC1C,OAAO;CAGT,MAAM,WAAW,IAAI,IAAqB,OAAO,QAAQ,MAAM,CAAC;CAEhE,OAAO,SAAS,OACb,CAAC,KAAK,iBACL,SAAS,IAAI,GAAG,KAAK,YAAY,aAAa,SAAS,IAAI,GAAG,CAAC,CACnE;AACF;;;;AAKA,MAAM,WAAW,SACf,IAAI,WAAW,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;;;;AAK9D,MAAM,iBAAiB,QAAoB,WACzC,OAAO,WAAW,OAAO,UACzB,OAAO,OAAO,MAAM,UAAU,SAAS,OAAO,MAAM;;;;;;;;;;;;AAatD,MAAM,oBACJ,UACA,WACY;CACZ,KAAK,MAAM,OAAO,SAAS,KAAK,GAC9B,IAAI,YAAY,KAAK,MAAM,GACzB,OAAO;AAGb"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/utils/is-not-nullish.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Type guard que verifica se um valor não é `null` nem `undefined`.
|
|
4
|
+
*
|
|
5
|
+
* @param value - Valor a ser verificado.
|
|
6
|
+
* @returns `true` se `value` não for `null` nem `undefined`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const values: (string | null | undefined)[] = ['a', null, 'b', undefined];
|
|
10
|
+
* const filtered: string[] = values.filter(isNotNullish);
|
|
11
|
+
*/
|
|
12
|
+
export declare const isNotNullish: <TValue>(value: TValue | null | undefined) => value is TValue;
|
|
13
|
+
//#endregion
|
|
14
|
+
//# sourceMappingURL=is-not-nullish.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/utils/is-not-nullish.ts
|
|
2
|
+
/**
|
|
3
|
+
* Type guard que verifica se um valor não é `null` nem `undefined`.
|
|
4
|
+
*
|
|
5
|
+
* @param value - Valor a ser verificado.
|
|
6
|
+
* @returns `true` se `value` não for `null` nem `undefined`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const values: (string | null | undefined)[] = ['a', null, 'b', undefined];
|
|
10
|
+
* const filtered: string[] = values.filter(isNotNullish);
|
|
11
|
+
*/
|
|
12
|
+
const isNotNullish = (value) => {
|
|
13
|
+
return value !== null && value !== void 0;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { isNotNullish };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=is-not-nullish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-not-nullish.js","names":[],"sources":["../../src/utils/is-not-nullish.ts"],"sourcesContent":["/**\n * Type guard que verifica se um valor não é `null` nem `undefined`.\n *\n * @param value - Valor a ser verificado.\n * @returns `true` se `value` não for `null` nem `undefined`.\n *\n * @example\n * const values: (string | null | undefined)[] = ['a', null, 'b', undefined];\n * const filtered: string[] = values.filter(isNotNullish);\n */\nexport const isNotNullish = <TValue>(\n value: TValue | null | undefined,\n): value is TValue => {\n return value !== null && value !== undefined;\n};\n"],"mappings":";;;;;;;;;;;AAUA,MAAa,gBACX,UACoB;CACpB,OAAO,UAAU,QAAQ,UAAU,KAAA;AACrC"}
|