inferred-types 0.54.8 → 0.54.9

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/README.md CHANGED
@@ -70,6 +70,20 @@ const people = pluralize("person");
70
70
  #### Data Patterns
71
71
 
72
72
  - types like `Url`, `IpAddress`, `CSV`, `DotPath`, `Hexadecimal`, `ZipCode`, and `DomainName` attempt to provide an out of the box type for common data structure patterns we find in the real world
73
+ - ISO3166 support (aka, countries):
74
+ - `Iso3166_Alpha2`, `Iso3166_Alpha3`, ...
75
+ - `isIso3166Alpha2()`, `isIsoAlpha3()`, type guards ...
76
+ - ISO8601 support (aka, datetime)
77
+ - `Iso8601DateTime`, `Iso8601Date`, `Iso8601Time`, ...
78
+ - `isIsoDateTime()`, `isIsoDate()`, `isIsoTime()`, ...
79
+
80
+ #### String Literal Matching at design time and run time
81
+
82
+ ```ts
83
+ const matcher = infer("{{ string }} is a {{ infer foo }} utility, that {{ infer bar }}");
84
+ // { foo: "fancy"; bar: "thinks it's better than you!"}
85
+ const fooBar = matcher("infer is a fancy utility, that thinks it's better than you!")
86
+ ```
73
87
 
74
88
  ### Numeric Literals
75
89
 
@@ -89,42 +103,73 @@ const people = pluralize("person");
89
103
 
90
104
  ### Object / Dictionaries
91
105
 
92
- 1. Based on an object's entity values:
93
-
94
- Assume a base type of `Obj`:
95
-
96
- ```ts
97
- type Obj = {
98
- n1: number;
99
- n2: 2;
100
- n3: 3;
101
- success: true;
102
- s1: string;
103
- s2: "hello";
104
- }
105
- ```
106
-
107
- We can get a union of string literals representing the _keys_ on the object whose value _extends_ some value:
108
-
109
- ```ts
110
- import type { KeysWithValue, KeysWithoutValue } from "inferred-types";
111
- // "s1" | "s2"
112
- type S = KeysWithValue<Obj, string>;
113
- // "success" | "n1" | "n2"
114
- type N = KeysWithoutValue<Obj, string>;
115
- ```
116
-
117
- > though less used, you can also use `KeysEqualValue` and `KeysNotEqualValue` for equality matching
118
-
119
- If you'd prefer to mutate the object's type rather than just identify the _keys_ which extend a value you can do this with: `WithValue` and `WithoutValue`:
120
-
121
- ```ts
122
- import type { WithValue, WithoutValue } from "inferred-types";
123
- // { s1: string; s2: "hello" }
124
- type S = WithValue<Obj, string>;
125
- // { success: true; n1: number; n2: 2; n3: 3 }
126
- type N = WithoutValue<Obj, string>;
127
- ```
106
+ #### Reduce Object to Keys with a knownValue
107
+
108
+ Assume a base type of `Obj`:
109
+
110
+ ```ts
111
+ type Obj = {
112
+ n1: number;
113
+ n2: 2;
114
+ n3: 3;
115
+ success: true;
116
+ s1: string;
117
+ s2: "hello";
118
+ }
119
+ ```
120
+
121
+ We can get a union of string literals representing the _keys_ on the object whose value _extends_ some value:
122
+
123
+ ```ts
124
+ import type { KeysWithValue, KeysWithoutValue } from "inferred-types";
125
+ // "s1" | "s2"
126
+ type S = KeysWithValue<Obj, string>;
127
+ // "success" | "n1" | "n2"
128
+ type N = KeysWithoutValue<Obj, string>;
129
+ ```
130
+
131
+ > though less used, you can also use `KeysEqualValue` and `KeysNotEqualValue` for equality matching
132
+
133
+ If you'd prefer to mutate the object's type rather than just identify the _keys_ which extend a value you can do this with: `WithValue` and `WithoutValue`:
134
+
135
+ ```ts
136
+ import type { WithValue, WithoutValue } from "inferred-types";
137
+ // { s1: string; s2: "hello" }
138
+ type S = WithValue<Obj, string>;
139
+ // { success: true; n1: number; n2: 2; n3: 3 }
140
+ type N = WithoutValue<Obj, string>;
141
+ ```
142
+
143
+ And at runtime:
144
+
145
+ ```ts
146
+ // { foo: "hi" }
147
+ const foo = withoutValue("number")({ foo: "hi", bar: 42, baz: 99 });
148
+ // { bar: 42 }
149
+ const bar = withoutValue("number(42,55,66)")({ foo: "hi", bar: 42, baz: 99 });
150
+
151
+ // { foo: "hi", bar: 42 }
152
+ const fooBar = withoutKeys("baz")({ foo: "hi", bar: 42, baz: 99 });
153
+ // { foo: "hi", bar: 42 }
154
+ const fooBar2 = withKeys("foo", "bar")({ foo: "hi", bar: 42, baz: 99 })
155
+ ```
156
+
157
+ #### Reduce Object's to only `Required` or `Optional` keys
158
+
159
+ ```ts
160
+ type Obj = { foo: string; bar?: string; baz?: number };
161
+ // "foo"
162
+ type ReqKeys = RequiredKeys<Obj>;
163
+ // ["foo"]
164
+ type ReqKeyTup = RequiredKeysTuple<Obj>;
165
+ // "bar" | "baz"
166
+ type OptKeys = OptionalKeys<Obj>;
167
+ // ["bar", "baz"]
168
+ type OptKeyTup = OptionalKeysTuple<Obj>;
169
+
170
+ type Reduced =
171
+
172
+ ```
128
173
 
129
174
  ## Contributing
130
175
 
@@ -430,12 +430,14 @@ __export(src_exports, {
430
430
  isLuminosityUom: () => isLuminosityUom,
431
431
  isLuxonDateTime: () => isLuxonDateTime,
432
432
  isMacysUrl: () => isMacysUrl,
433
+ isMap: () => isMap,
433
434
  isMapToken: () => isMapToken,
434
435
  isMassMetric: () => isMassMetric,
435
436
  isMassUom: () => isMassUom,
436
437
  isMetric: () => isMetric,
437
438
  isMexicanNewsUrl: () => isMexicanNewsUrl,
438
439
  isMoment: () => isMoment,
440
+ isNarrowableObject: () => isNarrowableObject,
439
441
  isNever: () => isNever,
440
442
  isNewsUrl: () => isNewsUrl,
441
443
  isNikeUrl: () => isNikeUrl,
@@ -470,6 +472,7 @@ __export(src_exports, {
470
472
  isSet: () => isSet,
471
473
  isSetBasedKind: () => isSetBasedKind,
472
474
  isSetBasedToken: () => isSetBasedToken,
475
+ isSetContainer: () => isSetContainer,
473
476
  isSetToken: () => isSetToken,
474
477
  isShape: () => isShape,
475
478
  isShapeCallback: () => isShapeCallback,
@@ -579,6 +582,7 @@ __export(src_exports, {
579
582
  narrowObjectToType: () => narrowObjectToType,
580
583
  never: () => never,
581
584
  objectToApi: () => objectToApi,
585
+ objectValues: () => objectValues,
582
586
  omit: () => omit,
583
587
  optional: () => optional,
584
588
  optionalOrNull: () => optionalOrNull,
@@ -655,6 +659,7 @@ __export(src_exports, {
655
659
  widen: () => widen,
656
660
  withDefaults: () => withDefaults,
657
661
  withKeys: () => withKeys,
662
+ withValue: () => withValue,
658
663
  withoutKeys: () => withoutKeys,
659
664
  withoutValue: () => withoutValue,
660
665
  wrapFn: () => wrapFn,
@@ -5258,6 +5263,16 @@ function narrowObjectToType() {
5258
5263
  }
5259
5264
  );
5260
5265
  }
5266
+ function objectValues(obj) {
5267
+ const tuple3 = Object.keys(obj).reduce(
5268
+ (acc, key) => [
5269
+ ...acc,
5270
+ obj[key]
5271
+ ],
5272
+ []
5273
+ );
5274
+ return tuple3;
5275
+ }
5261
5276
  function omit(obj, ...removeKeys) {
5262
5277
  const keys = Object.keys(obj);
5263
5278
  return keys.reduce(
@@ -5308,12 +5323,110 @@ function withKeys(dict, ...keys) {
5308
5323
  function withoutKeys(dict, ...exclude) {
5309
5324
  return omit(dict, ...exclude);
5310
5325
  }
5311
- function withoutValue(val) {
5326
+ function doesExtend(type) {
5327
+ return (val) => {
5328
+ let response = false;
5329
+ if (isString(val)) {
5330
+ if (type === "string") {
5331
+ response = true;
5332
+ }
5333
+ if (type.startsWith("string(")) {
5334
+ const literals = stripAfter(
5335
+ stripBefore(type, "string("),
5336
+ ")"
5337
+ ).split(/,\s*/);
5338
+ if (literals.includes(val)) {
5339
+ response = true;
5340
+ }
5341
+ }
5342
+ }
5343
+ if (isNumber(val)) {
5344
+ if (type === "number") {
5345
+ response = true;
5346
+ }
5347
+ if (type.startsWith("number(")) {
5348
+ const literals = stripAfter(
5349
+ stripBefore(type, "number("),
5350
+ ")"
5351
+ ).split(/,\s*/).map(Number);
5352
+ if (literals.includes(val)) {
5353
+ response = true;
5354
+ }
5355
+ }
5356
+ }
5357
+ if (isNull(val) && (type === "null" || type === "Opt<null>")) {
5358
+ response = true;
5359
+ }
5360
+ if (isUndefined(val) && (type === "undefined" || type.startsWith("Opt<"))) {
5361
+ response = true;
5362
+ }
5363
+ if (isBoolean(val)) {
5364
+ if (type === "boolean") {
5365
+ response = true;
5366
+ }
5367
+ if (type === "true" && val === true || type === "false" && val === false) {
5368
+ response = true;
5369
+ }
5370
+ }
5371
+ if (isNarrowableObject(val)) {
5372
+ if (type === "Dict" || type === "Dict<string, unknown>") {
5373
+ response = true;
5374
+ }
5375
+ if (startsWith("Dict<")(type)) {
5376
+ const match = infer("Dict<{{infer key}}, {{infer value}}>")(type);
5377
+ if (match) {
5378
+ const { value } = match;
5379
+ const isOpt = value.includes(`Opt<`);
5380
+ const values = objectValues(val);
5381
+ if (values.every((i) => isOpt ? isString(i) || isUndefined(i) : isString(i)) && type === "Dict<string, string>" || values.every((i) => isOpt ? isUndefined(i) || isNumber(i) : isNumber(i)) && type === "Dict<string, number>" || values.every((i) => isOpt ? isUndefined(i) || isBoolean(i) : isBoolean(i)) && type === "Dict<string, boolean>") {
5382
+ response = true;
5383
+ }
5384
+ }
5385
+ }
5386
+ }
5387
+ if (isArray(val)) {
5388
+ if (type === "Array" || type === "Array<unknown>") {
5389
+ return true;
5390
+ }
5391
+ if (type === "Array<Dict>" && val.every(isObject) || type === "Array<boolean>" && val.every(isBoolean) || type === "Array<string>" && val.every(isString) || type === "Array<number>" && val.every(isNumber) || type === "Array<Map>" && val.every(isMap) || type === "Array<Set>" && val.every(isSetContainer)) {
5392
+ response = true;
5393
+ }
5394
+ }
5395
+ if (isMap(val)) {
5396
+ if (type === "Map" || type === "Map<Dict, Array>" && Array.from(val.keys()).every(isObject) && Array.from(val.values()).every(isArray) || type === "Map<Dict, Dict>" && Array.from(val.keys()).every(isObject) && Array.from(val.values()).every(isObject) || type === "Map<Dict, boolean>" && Array.from(val.keys()).every(isObject) && Array.from(val.values()).every(isBoolean) || type === "Map<Dict, number>" && Array.from(val.keys()).every(isObject) && Array.from(val.values()).every(isNumber) || type === "Map<Dict, string>" && Array.from(val.keys()).every(isObject) && Array.from(val.values()).every(isString) || type === "Map<Dict, unknown>" && Array.from(val.keys()).every(isObject) || type === "Map<string, string>" && Array.from(val.keys()).every(isString) && Array.from(val.values()).every(isString) || type === "Map<string, number>" && Array.from(val.keys()).every(isString) && Array.from(val.values()).every(isNumber) || type === "Map<string, boolean>" && Array.from(val.keys()).every(isString) && Array.from(val.values()).every(isBoolean) || type === "Map<string, unknown>" && Array.from(val.keys()).every(isString) || type === "Map<number, string>" && Array.from(val.keys()).every(isNumber) && Array.from(val.values()).every(isString) || type === "Map<number, number>" && Array.from(val.keys()).every(isNumber) && Array.from(val.values()).every(isNumber) || type === "Map<number, boolean>" && Array.from(val.keys()).every(isNumber) && Array.from(val.values()).every(isBoolean) || type === "Map<number, unknown>" && Array.from(val.keys()).every(isNumber)) {
5397
+ response = true;
5398
+ }
5399
+ }
5400
+ if (isSetContainer(val)) {
5401
+ if (type === "Set" || type === "Set<unknown>" || type === "Set<boolean>" && Array.from(val).every(isBoolean) || type === "Set<string>" && Array.from(val).every(isString) || type === "Set<number>" && Array.from(val).every(isNumber) || type === "Set<Opt<boolean>>" && Array.from(val).every((i) => isBoolean(i) || isUndefined(i)) || type === "Set<Opt<string>>" && Array.from(val).every((i) => isString(i) || isUndefined(i)) || type === "Set<Opt<number>>" && Array.from(val).every((i) => isNumber(i) || isUndefined(i))) {
5402
+ response = true;
5403
+ }
5404
+ }
5405
+ return response;
5406
+ };
5407
+ }
5408
+ function withoutValue(wo) {
5312
5409
  return (obj) => {
5313
- return Object.keys(obj).reduce(
5314
- (acc, key) => val === obj[key] ? acc : { ...acc, [key]: obj[key] },
5315
- {}
5316
- );
5410
+ const output = {};
5411
+ for (const key of keysOf(obj)) {
5412
+ const val = obj[key];
5413
+ if (!doesExtend(wo)(val)) {
5414
+ output[key] = val;
5415
+ }
5416
+ }
5417
+ return output;
5418
+ };
5419
+ }
5420
+ function withValue(wo) {
5421
+ return (obj) => {
5422
+ const output = {};
5423
+ for (const key of keysOf(obj)) {
5424
+ const val = obj[key];
5425
+ if (doesExtend(wo)(val)) {
5426
+ output[key] = val;
5427
+ }
5428
+ }
5429
+ return output;
5317
5430
  };
5318
5431
  }
5319
5432
  function createErrorCondition(kind, msg = "", utility = "") {
@@ -5532,6 +5645,9 @@ function isFunction(value) {
5532
5645
  function isObject(value) {
5533
5646
  return typeof value === "object" && value !== null && Array.isArray(value) === false;
5534
5647
  }
5648
+ function isNarrowableObject(value) {
5649
+ return isObject(value) && Object.keys(value).every((key) => ["string", "number", "boolean", "symbol", "object", "undefined", "void", "null"].includes(typeof value[key]));
5650
+ }
5535
5651
  function isEscapeFunction(val) {
5536
5652
  return isFunction(val) && "escape" in val && val.escape === true;
5537
5653
  }
@@ -6088,6 +6204,9 @@ function isIndexable(value) {
6088
6204
  function isInlineSvg(v) {
6089
6205
  return isString(v) && v.trim().startsWith(`<svg`) && v.trim().endsWith(`</svg>`);
6090
6206
  }
6207
+ function isMap(val) {
6208
+ return val instanceof Map;
6209
+ }
6091
6210
  function isNever(val) {
6092
6211
  return isConstant(val) && val.kind === "never";
6093
6212
  }
@@ -6136,6 +6255,12 @@ function isLikeRegExp(val) {
6136
6255
  }
6137
6256
  return false;
6138
6257
  }
6258
+ function isSet(val) {
6259
+ return isObject(val) ? val.kind !== "Unset" : true;
6260
+ }
6261
+ function isSetContainer(val) {
6262
+ return val instanceof Set;
6263
+ }
6139
6264
  function isStringArray(val) {
6140
6265
  return Array.isArray(val) && val.every((i) => isString(i));
6141
6266
  }
@@ -6160,9 +6285,6 @@ function isTypeTuple(value) {
6160
6285
  function isUnset(val) {
6161
6286
  return isObject(val) && val.kind === "Unset";
6162
6287
  }
6163
- function isSet(val) {
6164
- return isObject(val) ? val.kind !== "Unset" : true;
6165
- }
6166
6288
  function isUri(val, ...protocols) {
6167
6289
  const p = protocols.length === 0 ? valuesOf(NETWORK_PROTOCOL_LOOKUP2).flat().filter((i) => i) : protocols;
6168
6290
  return isString(val) && p.some((i) => val.startsWith(`${i}://`));
@@ -8143,12 +8265,14 @@ var ExifSaturation = /* @__PURE__ */ ((ExifSaturation2) => {
8143
8265
  isLuminosityUom,
8144
8266
  isLuxonDateTime,
8145
8267
  isMacysUrl,
8268
+ isMap,
8146
8269
  isMapToken,
8147
8270
  isMassMetric,
8148
8271
  isMassUom,
8149
8272
  isMetric,
8150
8273
  isMexicanNewsUrl,
8151
8274
  isMoment,
8275
+ isNarrowableObject,
8152
8276
  isNever,
8153
8277
  isNewsUrl,
8154
8278
  isNikeUrl,
@@ -8183,6 +8307,7 @@ var ExifSaturation = /* @__PURE__ */ ((ExifSaturation2) => {
8183
8307
  isSet,
8184
8308
  isSetBasedKind,
8185
8309
  isSetBasedToken,
8310
+ isSetContainer,
8186
8311
  isSetToken,
8187
8312
  isShape,
8188
8313
  isShapeCallback,
@@ -8292,6 +8417,7 @@ var ExifSaturation = /* @__PURE__ */ ((ExifSaturation2) => {
8292
8417
  narrowObjectToType,
8293
8418
  never,
8294
8419
  objectToApi,
8420
+ objectValues,
8295
8421
  omit,
8296
8422
  optional,
8297
8423
  optionalOrNull,
@@ -8368,6 +8494,7 @@ var ExifSaturation = /* @__PURE__ */ ((ExifSaturation2) => {
8368
8494
  widen,
8369
8495
  withDefaults,
8370
8496
  withKeys,
8497
+ withValue,
8371
8498
  withoutKeys,
8372
8499
  withoutValue,
8373
8500
  wrapFn,