@lucasbernardosn/ts-utils 0.0.0-stage → 0.3.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +52 -2
  3. package/dist/dev/index.d.ts +2 -0
  4. package/dist/dev/index.js +2 -0
  5. package/dist/dev/sleep.d.ts +32 -0
  6. package/dist/dev/sleep.js +42 -0
  7. package/dist/dev/sleep.js.map +1 -0
  8. package/dist/index.d.ts +29 -0
  9. package/dist/index.js +9 -0
  10. package/dist/types/any.d.ts +33 -0
  11. package/dist/types/any.js +0 -0
  12. package/dist/types/array.d.ts +33 -0
  13. package/dist/types/array.js +0 -0
  14. package/dist/types/deep-keys-flat.d.ts +36 -0
  15. package/dist/types/deep-keys-flat.js +0 -0
  16. package/dist/types/deep-keys.d.ts +57 -0
  17. package/dist/types/deep-keys.js +0 -0
  18. package/dist/types/deep-partial.d.ts +39 -0
  19. package/dist/types/deep-partial.js +0 -0
  20. package/dist/types/deep-readonly.d.ts +39 -0
  21. package/dist/types/deep-readonly.js +0 -0
  22. package/dist/types/deep-value.d.ts +32 -0
  23. package/dist/types/deep-value.js +0 -0
  24. package/dist/types/ensure-string.d.ts +19 -0
  25. package/dist/types/ensure-string.js +0 -0
  26. package/dist/types/index.d.ts +21 -0
  27. package/dist/types/index.js +0 -0
  28. package/dist/types/keys-of-type.d.ts +26 -0
  29. package/dist/types/keys-of-type.js +0 -0
  30. package/dist/types/merge-override.d.ts +34 -0
  31. package/dist/types/merge-override.js +0 -0
  32. package/dist/types/nullish.d.ts +25 -0
  33. package/dist/types/nullish.js +0 -0
  34. package/dist/types/omit-by-value.d.ts +31 -0
  35. package/dist/types/omit-by-value.js +0 -0
  36. package/dist/types/optional.d.ts +29 -0
  37. package/dist/types/optional.js +0 -0
  38. package/dist/types/pick-by-value.d.ts +30 -0
  39. package/dist/types/pick-by-value.js +0 -0
  40. package/dist/types/recompose.d.ts +26 -0
  41. package/dist/types/recompose.js +0 -0
  42. package/dist/types/required-except.d.ts +31 -0
  43. package/dist/types/required-except.js +0 -0
  44. package/dist/types/serializable-value.d.ts +23 -0
  45. package/dist/types/serializable-value.js +0 -0
  46. package/dist/types/strict-empty-object.d.ts +12 -0
  47. package/dist/types/strict-empty-object.js +0 -0
  48. package/dist/types/unknown.d.ts +33 -0
  49. package/dist/types/unknown.js +0 -0
  50. package/dist/types/value-of.d.ts +20 -0
  51. package/dist/types/value-of.js +0 -0
  52. package/dist/utils/compose-event-handlers.d.ts +18 -0
  53. package/dist/utils/compose-event-handlers.js +22 -0
  54. package/dist/utils/compose-event-handlers.js.map +1 -0
  55. package/dist/utils/create-split-props.d.ts +38 -0
  56. package/dist/utils/create-split-props.js +36 -0
  57. package/dist/utils/create-split-props.js.map +1 -0
  58. package/dist/utils/get-initials.d.ts +15 -0
  59. package/dist/utils/get-initials.js +21 -0
  60. package/dist/utils/get-initials.js.map +1 -0
  61. package/dist/utils/index.d.ts +8 -0
  62. package/dist/utils/index.js +8 -0
  63. package/dist/utils/is-deep-equal.d.ts +24 -0
  64. package/dist/utils/is-deep-equal.js +110 -0
  65. package/dist/utils/is-deep-equal.js.map +1 -0
  66. package/dist/utils/is-not-nullish.d.ts +14 -0
  67. package/dist/utils/is-not-nullish.js +18 -0
  68. package/dist/utils/is-not-nullish.js.map +1 -0
  69. package/dist/utils/merge-booleans.d.ts +25 -0
  70. package/dist/utils/merge-booleans.js +37 -0
  71. package/dist/utils/merge-booleans.js.map +1 -0
  72. package/dist/utils/to-pascal-case.d.ts +18 -0
  73. package/dist/utils/to-pascal-case.js +17 -0
  74. package/dist/utils/to-pascal-case.js.map +1 -0
  75. package/package.json +41 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lucas Bernardo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,53 @@
1
- # Temporary Holding Version
1
+ # @lucasbernardosn/ts-utils
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Funções e helpers de tipo em TypeScript puro, sem React e sem dependências. Serve a qualquer
4
+ projeto TypeScript e é a base do [`@lucasbernardosn/react-ui`](https://www.npmjs.com/package/@lucasbernardosn/react-ui)
5
+ e do [`@lucasbernardosn/react-table`](https://www.npmjs.com/package/@lucasbernardosn/react-table).
6
+
7
+ Substitui o `@lucasbernardosn/utils`: a troca é só do nome no import.
8
+
9
+ ## Instalação
10
+
11
+ ```bash
12
+ pnpm add @lucasbernardosn/ts-utils
13
+ ```
14
+
15
+ Tudo sai da raiz do pacote:
16
+
17
+ ```ts
18
+ import { getInitials, isDeepEqual, type DeepPartial } from '@lucasbernardosn/ts-utils';
19
+ ```
20
+
21
+ ## Funções
22
+
23
+ | Função | Para quê |
24
+ | ------ | -------- |
25
+ | `composeEventHandlers` | Junta vários handlers num só, chamados em sequência com os mesmos argumentos; os `undefined` são ignorados |
26
+ | `createSplitProps` | Separa um objeto de props em dois pela lista de chaves, que precisa cobrir todas as chaves do tipo pedido |
27
+ | `getInitials` | As iniciais de um nome, em maiúsculas: a do primeiro e a do último nome |
28
+ | `isDeepEqual` | Igualdade estrutural, inclusive de `Map`, `Set`, `Date`, `RegExp` e arrays tipados |
29
+ | `isNotNullish` | Guard que tira `null` e `undefined` do tipo, para usar no `filter` |
30
+ | `mergeBooleansAnd`, `mergeBooleansOr` | Combinam booleanos com E e OU, ignorando os `null` e `undefined` |
31
+ | `toPascalCase` | Converte texto para PascalCase, separando em `-`, `_` e espaços |
32
+ | `sleep` | Promise que resolve depois de um tempo, opcionalmente com um valor (para testes e protótipos) |
33
+
34
+ ## Tipos
35
+
36
+ | Tipo | Para quê |
37
+ | ---- | -------- |
38
+ | `DeepPartial`, `DeepReadonly` | `Partial` e `Readonly` em todos os níveis |
39
+ | `DeepKeys`, `DeepKeysFlat`, `DeepValue` | Os caminhos de um objeto (`'a.b.c'`) e o tipo do valor em cada um |
40
+ | `KeysOfType`, `PickByValue`, `OmitByValue` | Chaves e recortes de um objeto pelo tipo do valor |
41
+ | `MergeOverride` | Junta dois tipos, com as chaves do segundo substituindo as do primeiro |
42
+ | `Optional`, `RequiredExcept` | Torna opcionais só as chaves pedidas, ou obrigatórias todas menos elas |
43
+ | `Recompose` | Achata uma interseção num objeto só, para o editor mostrar o tipo final |
44
+ | `ValueOf`, `ArrayElement`, `NonEmptyArray` | O tipo dos valores de um objeto, o elemento de um array e um array com ao menos um item |
45
+ | `Nullish`, `EnsureString`, `PascalCase` | `null` ou `undefined`, o tipo que só aceita `string` e o PascalCase de um literal |
46
+ | `SerializableValue`, `StrictEmptyObject` | Um valor que sobrevive ao `JSON.stringify` e o objeto sem chaves |
47
+ | `AnyType`, `UnknownType` e variantes | Os `any` e `unknown` nomeados (`AnyObject`, `UnknownFunction`…), para o uso ser explícito |
48
+
49
+ O JSDoc de cada função e tipo, no editor, traz os detalhes e os exemplos.
50
+
51
+ ## Licença
52
+
53
+ MIT.
@@ -0,0 +1,2 @@
1
+ import { sleep } from "./sleep.js";
2
+ export { sleep };
@@ -0,0 +1,2 @@
1
+ import { sleep } from "./sleep.js";
2
+ export { sleep };
@@ -0,0 +1,32 @@
1
+ //#region src/dev/sleep.d.ts
2
+ /**
3
+ * Opções de configuração do {@link sleep}.
4
+ */
5
+ type SleepOptions = {
6
+ /** Sinal para cancelar o delay (útil em testes e para testar unmount). */
7
+ signal?: AbortSignal;
8
+ /** Chance de simular um erro randômico, de 0.0 a 1.0 (ex.: 0.3 = 30% de chance de falha). */
9
+ failureRate?: number;
10
+ /** Mensagem de erro customizada caso ocorra a falha simulada. */
11
+ errorMessage?: string;
12
+ };
13
+ /**
14
+ * Opções do {@link sleep} que resolve com um valor.
15
+ */
16
+ type SleepOptionsWithValue<T> = SleepOptions & {
17
+ /** Valor que será retornado após o delay (útil para mockar respostas de API). */
18
+ resolveWith: T;
19
+ };
20
+ /**
21
+ * Função utilitária para desenvolvimento que pausa a execução por um tempo.
22
+ * Excelente para mockar latência de rede, testar estados de loading e simular falhas.
23
+ *
24
+ * @param ms Tempo em milissegundos ou um range `[min, max]` para latência aleatória. Padrão é 1000ms.
25
+ * @param options Opções adicionais (cancelamento, valor de resolução e simulação de falha).
26
+ * @returns Promise resolvida com `options.resolveWith` após o delay, rejeitada em caso de
27
+ * abort (com `signal.reason`) ou de falha simulada (com `errorMessage`).
28
+ */
29
+ export declare function sleep(ms?: number | [min: number, max: number], options?: SleepOptions): Promise<void>;
30
+ export declare function sleep<T>(ms: number | [min: number, max: number], options: SleepOptionsWithValue<T>): Promise<T>;
31
+ //#endregion
32
+ //# sourceMappingURL=sleep.d.ts.map
@@ -0,0 +1,42 @@
1
+ //#region src/dev/sleep.ts
2
+ /**
3
+ * Calcula o delay em milissegundos a partir do parâmetro `ms` do {@link sleep}.
4
+ * Se `ms` for um range `[min, max]`, sorteia um valor inteiro dentro do intervalo (inclusive).
5
+ */
6
+ const resolveDelay = (ms) => {
7
+ if (!Array.isArray(ms)) return ms;
8
+ const [min, max] = ms;
9
+ return Math.floor(Math.random() * (max - min + 1) + min);
10
+ };
11
+ /**
12
+ * Sobrecarga, e por isso `function`: com `resolveWith`, a promise resolve com o tipo dele; sem, com
13
+ * `void`. Uma assinatura só com o valor opcional resolveria `undefined` como se fosse `T`.
14
+ */
15
+ function sleep(ms = 1e3, options) {
16
+ const delay = resolveDelay(ms);
17
+ const { signal, failureRate = 0, errorMessage = "Simulated sleep failure" } = options ?? {};
18
+ const resolveWith = options && "resolveWith" in options ? options.resolveWith : void 0;
19
+ return new Promise((resolve, reject) => {
20
+ if (signal?.aborted) {
21
+ reject(signal.reason);
22
+ return;
23
+ }
24
+ const handleAbort = () => {
25
+ clearTimeout(timer);
26
+ reject(signal?.reason);
27
+ };
28
+ const timer = setTimeout(() => {
29
+ signal?.removeEventListener("abort", handleAbort);
30
+ if (failureRate > 0 && Math.random() < failureRate) {
31
+ reject(new Error(errorMessage));
32
+ return;
33
+ }
34
+ resolve(resolveWith);
35
+ }, delay);
36
+ signal?.addEventListener("abort", handleAbort, { once: true });
37
+ });
38
+ }
39
+ //#endregion
40
+ export { sleep };
41
+
42
+ //# sourceMappingURL=sleep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.js","names":[],"sources":["../../src/dev/sleep.ts"],"sourcesContent":["/**\n * Opções de configuração do {@link sleep}.\n */\ntype SleepOptions = {\n /** Sinal para cancelar o delay (útil em testes e para testar unmount). */\n signal?: AbortSignal;\n /** Chance de simular um erro randômico, de 0.0 a 1.0 (ex.: 0.3 = 30% de chance de falha). */\n failureRate?: number;\n /** Mensagem de erro customizada caso ocorra a falha simulada. */\n errorMessage?: string;\n};\n\n/**\n * Opções do {@link sleep} que resolve com um valor.\n */\ntype SleepOptionsWithValue<T> = SleepOptions & {\n /** Valor que será retornado após o delay (útil para mockar respostas de API). */\n resolveWith: T;\n};\n\n/**\n * Calcula o delay em milissegundos a partir do parâmetro `ms` do {@link sleep}.\n * Se `ms` for um range `[min, max]`, sorteia um valor inteiro dentro do intervalo (inclusive).\n */\nconst resolveDelay = (ms: number | [min: number, max: number]): number => {\n if (!Array.isArray(ms)) {\n return ms;\n }\n\n const [min, max] = ms;\n return Math.floor(Math.random() * (max - min + 1) + min);\n};\n\n/**\n * Função utilitária para desenvolvimento que pausa a execução por um tempo.\n * Excelente para mockar latência de rede, testar estados de loading e simular falhas.\n *\n * @param ms Tempo em milissegundos ou um range `[min, max]` para latência aleatória. Padrão é 1000ms.\n * @param options Opções adicionais (cancelamento, valor de resolução e simulação de falha).\n * @returns Promise resolvida com `options.resolveWith` após o delay, rejeitada em caso de\n * abort (com `signal.reason`) ou de falha simulada (com `errorMessage`).\n */\nexport function sleep(\n ms?: number | [min: number, max: number],\n options?: SleepOptions,\n): Promise<void>;\nexport function sleep<T>(\n ms: number | [min: number, max: number],\n options: SleepOptionsWithValue<T>,\n): Promise<T>;\n/**\n * Sobrecarga, e por isso `function`: com `resolveWith`, a promise resolve com o tipo dele; sem, com\n * `void`. Uma assinatura só com o valor opcional resolveria `undefined` como se fosse `T`.\n */\nexport function sleep<T>(\n ms: number | [min: number, max: number] = 1000,\n options?: SleepOptions | SleepOptionsWithValue<T>,\n): Promise<T | undefined> {\n const delay = resolveDelay(ms);\n const {\n signal,\n failureRate = 0,\n errorMessage = 'Simulated sleep failure',\n } = options ?? {};\n const resolveWith =\n options && 'resolveWith' in options ? options.resolveWith : undefined;\n\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const handleAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n\n const timer = setTimeout(() => {\n // Remove o listener de abort: o timer já completou, cancelar não faz mais sentido.\n signal?.removeEventListener('abort', handleAbort);\n\n // Simulação de chaos (falhas de API).\n if (failureRate > 0 && Math.random() < failureRate) {\n reject(new Error(errorMessage));\n return;\n }\n\n resolve(resolveWith);\n }, delay);\n\n // Permite cancelamento externo enquanto o timer está pendente.\n signal?.addEventListener('abort', handleAbort, { once: true });\n });\n}\n"],"mappings":";;;;;AAwBA,MAAM,gBAAgB,OAAoD;CACxE,IAAI,CAAC,MAAM,QAAQ,EAAE,GACnB,OAAO;CAGT,MAAM,CAAC,KAAK,OAAO;CACnB,OAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,KAAK,GAAG;AACzD;;;;;AAuBA,SAAgB,MACd,KAA0C,KAC1C,SACwB;CACxB,MAAM,QAAQ,aAAa,EAAE;CAC7B,MAAM,EACJ,QACA,cAAc,GACd,eAAe,8BACb,WAAW,CAAC;CAChB,MAAM,cACJ,WAAW,iBAAiB,UAAU,QAAQ,cAAc,KAAA;CAE9D,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI,QAAQ,SAAS;GACnB,OAAO,OAAO,MAAM;GACpB;EACF;EAEA,MAAM,oBAAoB;GACxB,aAAa,KAAK;GAClB,OAAO,QAAQ,MAAM;EACvB;EAEA,MAAM,QAAQ,iBAAiB;GAE7B,QAAQ,oBAAoB,SAAS,WAAW;GAGhD,IAAI,cAAc,KAAK,KAAK,OAAO,IAAI,aAAa;IAClD,OAAO,IAAI,MAAM,YAAY,CAAC;IAC9B;GACF;GAEA,QAAQ,WAAW;EACrB,GAAG,KAAK;EAGR,QAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,KAAK,CAAC;CAC/D,CAAC;AACH"}
@@ -0,0 +1,29 @@
1
+ import { sleep } from "./dev/sleep.js";
2
+ import { AnyArray, AnyFunction, AnyLooseValue, AnyObject, AnyType } from "./types/any.js";
3
+ import { ArrayElement, NonEmptyArray } from "./types/array.js";
4
+ import { DeepKeys } from "./types/deep-keys.js";
5
+ import { DeepKeysFlat } from "./types/deep-keys-flat.js";
6
+ import { DeepPartial } from "./types/deep-partial.js";
7
+ import { DeepReadonly } from "./types/deep-readonly.js";
8
+ import { DeepValue } from "./types/deep-value.js";
9
+ import { EnsureString } from "./types/ensure-string.js";
10
+ import { KeysOfType } from "./types/keys-of-type.js";
11
+ import { MergeOverride } from "./types/merge-override.js";
12
+ import { Nullish } from "./types/nullish.js";
13
+ import { OmitByValue } from "./types/omit-by-value.js";
14
+ import { Optional } from "./types/optional.js";
15
+ import { PickByValue } from "./types/pick-by-value.js";
16
+ import { Recompose } from "./types/recompose.js";
17
+ import { RequiredExcept } from "./types/required-except.js";
18
+ import { SerializableValue } from "./types/serializable-value.js";
19
+ import { StrictEmptyObject } from "./types/strict-empty-object.js";
20
+ import { UnknownArray, UnknownFunction, UnknownLooseValue, UnknownObject, UnknownType } from "./types/unknown.js";
21
+ import { ValueOf } from "./types/value-of.js";
22
+ import { composeEventHandlers } from "./utils/compose-event-handlers.js";
23
+ import { createSplitProps } from "./utils/create-split-props.js";
24
+ import { getInitials } from "./utils/get-initials.js";
25
+ import { isDeepEqual } from "./utils/is-deep-equal.js";
26
+ import { isNotNullish } from "./utils/is-not-nullish.js";
27
+ import { mergeBooleansAnd, mergeBooleansOr } from "./utils/merge-booleans.js";
28
+ import { PascalCase, toPascalCase } from "./utils/to-pascal-case.js";
29
+ export { AnyArray, AnyFunction, AnyLooseValue, AnyObject, AnyType, ArrayElement, DeepKeys, DeepKeysFlat, DeepPartial, DeepReadonly, DeepValue, EnsureString, KeysOfType, MergeOverride, NonEmptyArray, Nullish, OmitByValue, Optional, PascalCase, PickByValue, Recompose, RequiredExcept, SerializableValue, StrictEmptyObject, UnknownArray, UnknownFunction, UnknownLooseValue, UnknownObject, UnknownType, ValueOf, composeEventHandlers, createSplitProps, getInitials, isDeepEqual, isNotNullish, mergeBooleansAnd, mergeBooleansOr, sleep, toPascalCase };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { sleep } from "./dev/sleep.js";
2
+ import { composeEventHandlers } from "./utils/compose-event-handlers.js";
3
+ import { createSplitProps } from "./utils/create-split-props.js";
4
+ import { getInitials } from "./utils/get-initials.js";
5
+ import { isDeepEqual } from "./utils/is-deep-equal.js";
6
+ import { isNotNullish } from "./utils/is-not-nullish.js";
7
+ import { mergeBooleansAnd, mergeBooleansOr } from "./utils/merge-booleans.js";
8
+ import { toPascalCase } from "./utils/to-pascal-case.js";
9
+ export { composeEventHandlers, createSplitProps, getInitials, isDeepEqual, isNotNullish, mergeBooleansAnd, mergeBooleansOr, sleep, toPascalCase };
@@ -0,0 +1,33 @@
1
+ //#region src/types/any.d.ts
2
+ /** biome-ignore-all lint/suspicious/noExplicitAny: "any" é usado para criar tipos genéricos */
3
+ /**
4
+ * Tipo genérico que representa qualquer valor possível no TipoScript.
5
+ * Utilizado como base para criação de estruturas de dados dinâmicas
6
+ * onde o tipo específico não é conhecido antecipadamente.
7
+ */
8
+ export type AnyType = any;
9
+ /**
10
+ * Tipo que representa um objeto genérico com chaves string e valores dinâmicos.
11
+ * Útil para modelar estruturas de dados flexíveis como payloads de API,
12
+ * configurações dinâmicas ou objetos com propriedades variáveis.
13
+ */
14
+ export type AnyObject = Record<string, AnyType>;
15
+ /**
16
+ * Tipo que representa um array genérico contendo elementos de qualquer tipo.
17
+ * Pode ser utilizado para modelar listas ou coleções onde o tipo dos elementos
18
+ * não é conhecido ou pode variar.
19
+ */
20
+ export type AnyArray = AnyType[];
21
+ /**
22
+ * Tipo que representa uma função genérica, aceitando qualquer quantidade
23
+ * de argumentos e retornando um valor de qualquer tipo.
24
+ */
25
+ export type AnyFunction = (...args: AnyType[]) => AnyType;
26
+ /**
27
+ * Tipo que representa um valor frouxamente tipado, podendo ser um primitivo,
28
+ * `null`, `undefined`, um objeto ou array dinâmico. Útil para modelar
29
+ * valores de origem incerta que ainda assim têm um conjunto limitado de formas possíveis.
30
+ */
31
+ export type AnyLooseValue = string | number | boolean | AnyObject | AnyArray | null | undefined;
32
+ //#endregion
33
+ //# sourceMappingURL=any.d.ts.map
File without changes
@@ -0,0 +1,33 @@
1
+ //#region src/types/array.d.ts
2
+ /**
3
+ * Tipo utilitário que extrai o tipo do elemento de um array.
4
+ * Retorna `never` caso `TArray` não seja um array.
5
+ *
6
+ * @template TArray - O tipo do array a ser avaliado.
7
+ *
8
+ * @example
9
+ *
10
+ * type Numeros = number[];
11
+ * type Numero = ArrayElement<Numeros>; // number
12
+ *
13
+ * type Strings = string[];
14
+ * type Str = ArrayElement<Strings>; // string
15
+ */
16
+ export type ArrayElement<TArray> = TArray extends (infer TElement)[] ? TElement : never;
17
+ /**
18
+ * Tipo utilitário que representa um array com pelo menos um elemento.
19
+ * Garante em tempo de compilação que o array não está vazio.
20
+ *
21
+ * @template TElement - Tipo dos elementos do array.
22
+ *
23
+ * @example
24
+ *
25
+ * type OpcoesSelecionadas = NonEmptyArray<string>;
26
+ *
27
+ * const valido: OpcoesSelecionadas = ['opcao1']; // OK
28
+ * const tambemValido: OpcoesSelecionadas = ['a', 'b', 'c']; // OK
29
+ * const invalido: OpcoesSelecionadas = []; // Erro de compilação
30
+ */
31
+ export type NonEmptyArray<TElement> = [TElement, ...TElement[]];
32
+ //#endregion
33
+ //# sourceMappingURL=array.d.ts.map
File without changes
@@ -0,0 +1,36 @@
1
+ import { AnyFunction } from "./any.js";
2
+ //#region src/types/deep-keys-flat.d.ts
3
+ /**
4
+ * Implementação recursiva de {@link DeepKeysFlat}, carregando o acumulador de
5
+ * profundidade `TDepth` para interromper a recursão ao atingir `TMaxDepth`.
6
+ */
7
+ type DeepKeysFlatImpl<TBase, TMaxDepth extends number, TDepth extends readonly unknown[]> = TDepth['length'] extends TMaxDepth ? never : NonNullable<TBase> extends AnyFunction | Date ? never : NonNullable<TBase> extends readonly (infer TElement)[] ? DeepKeysFlatImpl<TElement, TMaxDepth, [...TDepth, unknown]> : NonNullable<TBase> extends object ? { [Key in Extract<keyof NonNullable<TBase>, string>]-?: Key | `${Key}.${DeepKeysFlatImpl<NonNullable<TBase>[Key], TMaxDepth, [...TDepth, unknown]>}`; }[Extract<keyof NonNullable<TBase>, string>] : never;
8
+ /**
9
+ * Tipo utilitário que extrai as chaves de um objeto em notação de ponto,
10
+ * achatando arrays de objetos ao estilo do TanStack Table: um caminho para
11
+ * dentro de um array não recebe índice numérico.
12
+ *
13
+ * Difere de `DeepKeys`, que trata arrays como folha. Use `DeepKeysFlat` quando
14
+ * precisar de paridade com `DeepKeys` do TanStack Table (definição de colunas).
15
+ *
16
+ * Atenção: `DeepValue` não resolve caminhos que atravessam arrays achatados —
17
+ * ele é o par de `DeepKeys` (folha), não de `DeepKeysFlat`.
18
+ *
19
+ * A recursão é limitada por `TMaxDepth` (padrão: 5).
20
+ *
21
+ * @template TBase - Tipo do objeto a ser inspecionado.
22
+ * @template TMaxDepth - Profundidade máxima de recursão. Padrão: 5.
23
+ *
24
+ * @example
25
+ *
26
+ * type Pedido = {
27
+ * id: string;
28
+ * itens: { produto: string; preco: number }[];
29
+ * };
30
+ *
31
+ * type Chaves = DeepKeysFlat<Pedido>;
32
+ * // 'id' | 'itens' | 'itens.produto' | 'itens.preco'
33
+ */
34
+ export type DeepKeysFlat<TBase, TMaxDepth extends number = 5> = DeepKeysFlatImpl<TBase, TMaxDepth, []>;
35
+ //#endregion
36
+ //# sourceMappingURL=deep-keys-flat.d.ts.map
File without changes
@@ -0,0 +1,57 @@
1
+ import { AnyArray, AnyFunction } from "./any.js";
2
+ //#region src/types/deep-keys.d.ts
3
+ /**
4
+ * Determina se um tipo deve ser tratado como um registro navegável
5
+ * (objeto com propriedades acessíveis via dot notation).
6
+ *
7
+ * Retorna `false` para `Date`, arrays e funções — mesmo que sejam objetos
8
+ * em tempo de execução, não fazem sentido como ramo de navegação de chaves.
9
+ *
10
+ * @template TValue - Tipo a ser avaliado.
11
+ */
12
+ type IsRecord<TValue> = NonNullable<TValue> extends AnyArray | AnyFunction | Date ? false : NonNullable<TValue> extends object ? true : false;
13
+ /**
14
+ * Implementação recursiva de {@link DeepKeys}, carregando o acumulador de
15
+ * profundidade `TDepth` para interromper a recursão ao atingir `TMaxDepth`.
16
+ */
17
+ type DeepKeysImpl<TBase, TMaxDepth extends number, TDepth extends readonly unknown[]> = TDepth['length'] extends TMaxDepth ? never : TBase extends AnyArray | AnyFunction | Date ? never : TBase extends object ? { [Key in Extract<keyof TBase, string>]-?: IsRecord<TBase[Key]> extends true ? Key | `${Key}.${DeepKeysImpl<NonNullable<TBase[Key]>, TMaxDepth, [...TDepth, unknown]>}` : Key; }[Extract<keyof TBase, string>] : never;
18
+ /**
19
+ * Tipo utilitário que extrai todas as chaves de um objeto em notação de ponto
20
+ * (dot notation), navegando recursivamente por objetos aninhados.
21
+ *
22
+ * Arrays são tratados como folha: `DeepKeys` para na chave do array e não
23
+ * gera caminhos para dentro dos elementos (`itens`, nunca `itens.0.preco`).
24
+ * Para achatar arrays de objetos ao estilo do TanStack Table
25
+ * (`itens.preco`), use `DeepKeysFlat`.
26
+ *
27
+ * A recursão é limitada por `TMaxDepth` (padrão: 5) para evitar explosão de
28
+ * união em entidades grandes e travamento do compilador.
29
+ *
30
+ * @template TBase - Tipo do objeto a ser inspecionado.
31
+ * @template TMaxDepth - Profundidade máxima de recursão. Padrão: 5.
32
+ *
33
+ * @example
34
+ *
35
+ * type Pedido = {
36
+ * id: string;
37
+ * cliente: {
38
+ * nome: string;
39
+ * documento?: { cpf: string };
40
+ * };
41
+ * itens: { produto: string }[];
42
+ * };
43
+ *
44
+ * type Chaves = DeepKeys<Pedido>;
45
+ * // 'id'
46
+ * // | 'cliente'
47
+ * // | 'cliente.nome'
48
+ * // | 'cliente.documento'
49
+ * // | 'cliente.documento.cpf'
50
+ * // | 'itens'
51
+ *
52
+ * type ChavesRasas = DeepKeys<Pedido, 1>;
53
+ * // 'id' | 'cliente' | 'itens'
54
+ */
55
+ export type DeepKeys<TBase, TMaxDepth extends number = 5> = DeepKeysImpl<TBase, TMaxDepth, []>;
56
+ //#endregion
57
+ //# sourceMappingURL=deep-keys.d.ts.map
File without changes
@@ -0,0 +1,39 @@
1
+ import { AnyFunction } from "./any.js";
2
+ //#region src/types/deep-partial.d.ts
3
+ /**
4
+ * Tipo utilitário que torna todas as propriedades de um tipo recursivamente opcionais,
5
+ * incluindo propriedades aninhadas em objetos e elementos de arrays.
6
+ * Funções são preservadas sem modificação.
7
+ *
8
+ * @template TBase - Tipo base a ser transformado.
9
+ *
10
+ * @example
11
+ *
12
+ * type Endereco = {
13
+ * rua: string;
14
+ * cidade: string;
15
+ * };
16
+ *
17
+ * type Usuario = {
18
+ * id: number;
19
+ * nome: string;
20
+ * endereco: Endereco;
21
+ * tags: string[];
22
+ * };
23
+ *
24
+ * type UsuarioParcial = DeepPartial<Usuario>;
25
+ *
26
+ * // Resultado:
27
+ * // {
28
+ * // id?: number;
29
+ * // nome?: string;
30
+ * // endereco?: {
31
+ * // rua?: string;
32
+ * // cidade?: string;
33
+ * // };
34
+ * // tags?: string[];
35
+ * // }
36
+ */
37
+ export type DeepPartial<TBase> = TBase extends AnyFunction ? TBase : TBase extends Array<infer TElement> ? DeepPartial<TElement>[] : TBase extends object ? { [Key in keyof TBase]?: DeepPartial<TBase[Key]>; } : TBase;
38
+ //#endregion
39
+ //# sourceMappingURL=deep-partial.d.ts.map
File without changes
@@ -0,0 +1,39 @@
1
+ import { AnyFunction } from "./any.js";
2
+ //#region src/types/deep-readonly.d.ts
3
+ /**
4
+ * Tipo utilitário que torna todas as propriedades de um tipo recursivamente somente-leitura,
5
+ * incluindo propriedades aninhadas em objetos. Arrays se tornam `ReadonlyArray`.
6
+ * Funções são preservadas sem modificação.
7
+ *
8
+ * @template TBase - Tipo base a ser transformado.
9
+ *
10
+ * @example
11
+ *
12
+ * type Endereco = {
13
+ * rua: string;
14
+ * cidade: string;
15
+ * };
16
+ *
17
+ * type Usuario = {
18
+ * id: number;
19
+ * nome: string;
20
+ * endereco: Endereco;
21
+ * tags: string[];
22
+ * };
23
+ *
24
+ * type UsuarioImutavel = DeepReadonly<Usuario>;
25
+ *
26
+ * // Resultado:
27
+ * // {
28
+ * // readonly id: number;
29
+ * // readonly nome: string;
30
+ * // readonly endereco: {
31
+ * // readonly rua: string;
32
+ * // readonly cidade: string;
33
+ * // };
34
+ * // readonly tags: ReadonlyArray<string>;
35
+ * // }
36
+ */
37
+ export type DeepReadonly<TBase> = TBase extends AnyFunction ? TBase : TBase extends Array<infer TElement> ? readonly DeepReadonly<TElement>[] : TBase extends object ? { readonly [Key in keyof TBase]: DeepReadonly<TBase[Key]>; } : TBase;
38
+ //#endregion
39
+ //# sourceMappingURL=deep-readonly.d.ts.map
File without changes
@@ -0,0 +1,32 @@
1
+ //#region src/types/deep-value.d.ts
2
+ /**
3
+ * Tipo utilitário que resolve o tipo do valor apontado por um caminho em
4
+ * notação de ponto (dot notation). É o par de `DeepKeys`: qualquer chave
5
+ * produzida por `DeepKeys<T>` é resolvível por `DeepValue<T, chave>`.
6
+ *
7
+ * Propriedades opcionais no meio do caminho são atravessadas (o `undefined`
8
+ * intermediário é ignorado). O `undefined` da propriedade final é preservado,
9
+ * refletindo o valor real em tempo de execução.
10
+ *
11
+ * Não resolve caminhos que atravessam arrays (ver `DeepKeysFlat`).
12
+ *
13
+ * @template TBase - Tipo do objeto raiz.
14
+ * @template TPath - Caminho em notação de ponto.
15
+ *
16
+ * @example
17
+ *
18
+ * type Pedido = {
19
+ * id: string;
20
+ * cliente: {
21
+ * nome: string;
22
+ * documento?: { cpf: string };
23
+ * };
24
+ * };
25
+ *
26
+ * type Id = DeepValue<Pedido, 'id'>; // string
27
+ * type Nome = DeepValue<Pedido, 'cliente.nome'>; // string
28
+ * type Cpf = DeepValue<Pedido, 'cliente.documento.cpf'>; // string | undefined
29
+ */
30
+ export type DeepValue<TBase, TPath extends string> = TPath extends `${infer Key}.${infer Rest}` ? Key extends keyof NonNullable<TBase> ? DeepValue<NonNullable<TBase>[Key], Rest> | Extract<TBase, null | undefined> : never : TPath extends keyof NonNullable<TBase> ? NonNullable<TBase>[TPath] | Extract<TBase, null | undefined> : never;
31
+ //#endregion
32
+ //# sourceMappingURL=deep-value.d.ts.map
File without changes
@@ -0,0 +1,19 @@
1
+ //#region src/types/ensure-string.d.ts
2
+ /**
3
+ * Tipo utilitário que garante que um tipo genérico seja uma string,
4
+ * retornando o próprio tipo se for string ou never se não for.
5
+ * Útil para validação de tipos em contextos onde apenas strings são aceitas.
6
+ *
7
+ * @template TString - Tipo a ser validado como string.
8
+ *
9
+ * @example
10
+ *
11
+ * // Quando o tipo é string, mantém string
12
+ * type S1 = EnsureString<string> // string
13
+ *
14
+ * // Quando o tipo não é string, resulta em never
15
+ * type S2 = EnsureString<number> // never
16
+ */
17
+ export type EnsureString<TString> = TString extends string ? TString : never;
18
+ //#endregion
19
+ //# sourceMappingURL=ensure-string.d.ts.map
File without changes
@@ -0,0 +1,21 @@
1
+ import { AnyArray, AnyFunction, AnyLooseValue, AnyObject, AnyType } from "./any.js";
2
+ import { ArrayElement, NonEmptyArray } from "./array.js";
3
+ import { DeepKeys } from "./deep-keys.js";
4
+ import { DeepKeysFlat } from "./deep-keys-flat.js";
5
+ import { DeepPartial } from "./deep-partial.js";
6
+ import { DeepReadonly } from "./deep-readonly.js";
7
+ import { DeepValue } from "./deep-value.js";
8
+ import { EnsureString } from "./ensure-string.js";
9
+ import { KeysOfType } from "./keys-of-type.js";
10
+ import { MergeOverride } from "./merge-override.js";
11
+ import { Nullish } from "./nullish.js";
12
+ import { OmitByValue } from "./omit-by-value.js";
13
+ import { Optional } from "./optional.js";
14
+ import { PickByValue } from "./pick-by-value.js";
15
+ import { Recompose } from "./recompose.js";
16
+ import { RequiredExcept } from "./required-except.js";
17
+ import { SerializableValue } from "./serializable-value.js";
18
+ import { StrictEmptyObject } from "./strict-empty-object.js";
19
+ import { UnknownArray, UnknownFunction, UnknownLooseValue, UnknownObject, UnknownType } from "./unknown.js";
20
+ import { ValueOf } from "./value-of.js";
21
+ export { AnyArray, AnyFunction, AnyLooseValue, AnyObject, AnyType, ArrayElement, DeepKeys, DeepKeysFlat, DeepPartial, DeepReadonly, DeepValue, EnsureString, KeysOfType, MergeOverride, NonEmptyArray, Nullish, OmitByValue, Optional, PickByValue, Recompose, RequiredExcept, SerializableValue, StrictEmptyObject, UnknownArray, UnknownFunction, UnknownLooseValue, UnknownObject, UnknownType, ValueOf };
File without changes
@@ -0,0 +1,26 @@
1
+ //#region src/types/keys-of-type.d.ts
2
+ /**
3
+ * Tipo utilitário que extrai as chaves de um objeto cujos valores estendem um tipo específico.
4
+ *
5
+ * @template TBase - Tipo base a ser inspecionado.
6
+ * @template TValue - Tipo dos valores que serão selecionados.
7
+ *
8
+ * @example
9
+ *
10
+ * type Usuario = {
11
+ * id: number;
12
+ * nome: string;
13
+ * email: string;
14
+ * ativo: boolean;
15
+ * idade: number;
16
+ * };
17
+ *
18
+ * type ChavesString = KeysOfType<Usuario, string>;
19
+ * // Resultado: 'nome' | 'email'
20
+ *
21
+ * type ChavesNumericas = KeysOfType<Usuario, number>;
22
+ * // Resultado: 'id' | 'idade'
23
+ */
24
+ export type KeysOfType<TBase, TValue> = { [Key in keyof TBase]: TBase[Key] extends TValue ? Key : never; }[keyof TBase];
25
+ //#endregion
26
+ //# sourceMappingURL=keys-of-type.d.ts.map
File without changes
@@ -0,0 +1,34 @@
1
+ //#region src/types/merge-override.d.ts
2
+ /**
3
+ * Tipo utilitário que combina dois tipos, substituindo as propriedades do tipo base
4
+ * pelas propriedades do tipo sobrescritor quando houver conflito de chaves.
5
+ *
6
+ * @template TBase - Tipo base a ser combinado.
7
+ * @template TOverride - Tipo cujas propriedades substituem as de TBase quando há conflito.
8
+ *
9
+ * @example
10
+ *
11
+ * type User = {
12
+ * id: number;
13
+ * name: string;
14
+ * };
15
+ *
16
+ * type NewUser = {
17
+ * id: string;
18
+ * login: string;
19
+ * age?: number;
20
+ * };
21
+ *
22
+ * type MergedUser = MergeOverride<User, NewUser>;
23
+ *
24
+ * // Resultado:
25
+ * // {
26
+ * // id: string;
27
+ * // name: string;
28
+ * // login: string;
29
+ * // age?: number;
30
+ * // }
31
+ */
32
+ export type MergeOverride<TBase, TOverride> = Omit<TBase, keyof TOverride> & TOverride;
33
+ //#endregion
34
+ //# sourceMappingURL=merge-override.d.ts.map
File without changes
@@ -0,0 +1,25 @@
1
+ //#region src/types/nullish.d.ts
2
+ /**
3
+ * Tipo utilitário que torna todas as propriedades de um tipo opcionais
4
+ * e permite que sejam nulas, mantendo o tipo original ou permitindo null.
5
+ *
6
+ * @template TBase - Tipo base de referência.
7
+ *
8
+ * @example
9
+ *
10
+ * type Usuario = {
11
+ * id: number;
12
+ * nome: string;
13
+ * ativo: boolean;
14
+ * };
15
+ *
16
+ * type UsuarioNullish = Nullish<Usuario>;
17
+ *
18
+ * // Exemplos de valores válidos
19
+ * const u1: UsuarioNullish = {};
20
+ * const u2: UsuarioNullish = { id: null };
21
+ * const u3: UsuarioNullish = { nome: 'Maria', ativo: null };
22
+ */
23
+ export type Nullish<TBase> = { [Key in keyof TBase]?: TBase[Key] | null; };
24
+ //#endregion
25
+ //# sourceMappingURL=nullish.d.ts.map
File without changes