@hy_ong/zod-kit 0.2.5 → 0.2.7

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.
@@ -11,6 +11,9 @@ var validateTaiwanTel = (value) => {
11
11
  return false;
12
12
  }
13
13
  const areaCode4 = cleanValue.substring(0, 4);
14
+ if (areaCode4 === "0700") {
15
+ return cleanValue.length === 10 && /^0700\d{6}$/.test(cleanValue);
16
+ }
14
17
  if (areaCode4 === "0800" || areaCode4 === "0809") {
15
18
  return cleanValue.length === 10 && /^080[09]\d{6}$/.test(cleanValue);
16
19
  }
@@ -11,6 +11,9 @@ var validateTaiwanTel = (value) => {
11
11
  return false;
12
12
  }
13
13
  const areaCode4 = cleanValue.substring(0, 4);
14
+ if (areaCode4 === "0700") {
15
+ return cleanValue.length === 10 && /^0700\d{6}$/.test(cleanValue);
16
+ }
14
17
  if (areaCode4 === "0800" || areaCode4 === "0809") {
15
18
  return cleanValue.length === 10 && /^080[09]\d{6}$/.test(cleanValue);
16
19
  }
@@ -10,7 +10,7 @@ import { L as Locale } from '../config-CABSSvAp.cjs';
10
10
  * Avoids z.preprocess() to preserve z.input types for React Hook Form compatibility.
11
11
  *
12
12
  * @author Ong Hoe Yuan
13
- * @version 0.2.5
13
+ * @version 0.2.6
14
14
  */
15
15
 
16
16
  /**
@@ -62,7 +62,7 @@ type ManyOfOptions<IsRequired extends boolean = true, V extends readonly (string
62
62
  * @template IsRequired - Whether the field is required
63
63
  * @template V - The tuple type of allowed values
64
64
  */
65
- type ManyOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number][], V[number][] | "" | null | undefined> : ZodType<V[number][] | null, V[number][] | "" | null | undefined>;
65
+ type ManyOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number][], V[number][]> : ZodType<V[number][] | null, V[number][] | "" | null | undefined>;
66
66
  /**
67
67
  * Creates a Zod schema for multi-select validation that restricts values to a predefined set
68
68
  *
@@ -10,7 +10,7 @@ import { L as Locale } from '../config-CABSSvAp.js';
10
10
  * Avoids z.preprocess() to preserve z.input types for React Hook Form compatibility.
11
11
  *
12
12
  * @author Ong Hoe Yuan
13
- * @version 0.2.5
13
+ * @version 0.2.6
14
14
  */
15
15
 
16
16
  /**
@@ -62,7 +62,7 @@ type ManyOfOptions<IsRequired extends boolean = true, V extends readonly (string
62
62
  * @template IsRequired - Whether the field is required
63
63
  * @template V - The tuple type of allowed values
64
64
  */
65
- type ManyOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number][], V[number][] | "" | null | undefined> : ZodType<V[number][] | null, V[number][] | "" | null | undefined>;
65
+ type ManyOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number][], V[number][]> : ZodType<V[number][] | null, V[number][] | "" | null | undefined>;
66
66
  /**
67
67
  * Creates a Zod schema for multi-select validation that restricts values to a predefined set
68
68
  *
@@ -7,11 +7,11 @@ import { L as Locale } from '../config-CABSSvAp.cjs';
7
7
  * Provides single-select validation that restricts input to a predefined set of allowed values,
8
8
  * with support for case-insensitive matching, default values, and transformation.
9
9
  *
10
- * Uses z.enum() internally to preserve literal type inference for both z.input and z.output,
11
- * making it compatible with React Hook Form resolvers and other type-aware form libraries.
10
+ * When required=true, z.input is narrowed to V[number] (no empty/null/undefined),
11
+ * making it fully compatible with React Hook Form resolvers and type-aware form libraries.
12
12
  *
13
13
  * @author Ong Hoe Yuan
14
- * @version 0.2.5
14
+ * @version 0.2.6
15
15
  */
16
16
 
17
17
  /**
@@ -51,12 +51,12 @@ type OneOfOptions<IsRequired extends boolean = true, V extends readonly (string
51
51
  * @template IsRequired - Whether the field is required
52
52
  * @template V - The tuple type of allowed values
53
53
  */
54
- type OneOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number], V[number] | "" | null | undefined> : ZodType<V[number] | null, V[number] | "" | null | undefined>;
54
+ type OneOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number], V[number]> : ZodType<V[number] | null, V[number] | "" | null | undefined>;
55
55
  /**
56
56
  * Creates a Zod schema for single-select validation that restricts values to a predefined set
57
57
  *
58
- * Uses z.enum() internally to preserve both z.input and z.output literal types,
59
- * ensuring compatibility with React Hook Form and other type-aware form libraries.
58
+ * When required=true, z.input is narrowed to V[number] only (no empty/null/undefined),
59
+ * ensuring full compatibility with React Hook Form and other type-aware form libraries.
60
60
  *
61
61
  * @template IsRequired - Whether the field is required (affects return type)
62
62
  * @template V - The tuple type of allowed values (inferred via const type parameter)
@@ -7,11 +7,11 @@ import { L as Locale } from '../config-CABSSvAp.js';
7
7
  * Provides single-select validation that restricts input to a predefined set of allowed values,
8
8
  * with support for case-insensitive matching, default values, and transformation.
9
9
  *
10
- * Uses z.enum() internally to preserve literal type inference for both z.input and z.output,
11
- * making it compatible with React Hook Form resolvers and other type-aware form libraries.
10
+ * When required=true, z.input is narrowed to V[number] (no empty/null/undefined),
11
+ * making it fully compatible with React Hook Form resolvers and type-aware form libraries.
12
12
  *
13
13
  * @author Ong Hoe Yuan
14
- * @version 0.2.5
14
+ * @version 0.2.6
15
15
  */
16
16
 
17
17
  /**
@@ -51,12 +51,12 @@ type OneOfOptions<IsRequired extends boolean = true, V extends readonly (string
51
51
  * @template IsRequired - Whether the field is required
52
52
  * @template V - The tuple type of allowed values
53
53
  */
54
- type OneOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number], V[number] | "" | null | undefined> : ZodType<V[number] | null, V[number] | "" | null | undefined>;
54
+ type OneOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true ? ZodType<V[number], V[number]> : ZodType<V[number] | null, V[number] | "" | null | undefined>;
55
55
  /**
56
56
  * Creates a Zod schema for single-select validation that restricts values to a predefined set
57
57
  *
58
- * Uses z.enum() internally to preserve both z.input and z.output literal types,
59
- * ensuring compatibility with React Hook Form and other type-aware form libraries.
58
+ * When required=true, z.input is narrowed to V[number] only (no empty/null/undefined),
59
+ * ensuring full compatibility with React Hook Form and other type-aware form libraries.
60
60
  *
61
61
  * @template IsRequired - Whether the field is required (affects return type)
62
62
  * @template V - The tuple type of allowed values (inferred via const type parameter)
package/dist/index.cjs CHANGED
@@ -50,7 +50,7 @@ var _chunkFP4O2ICMcjs = require('./chunk-FP4O2ICM.cjs');
50
50
 
51
51
 
52
52
 
53
- var _chunkVKBNKPFOcjs = require('./chunk-VKBNKPFO.cjs');
53
+ var _chunkV2WFT5M2cjs = require('./chunk-V2WFT5M2.cjs');
54
54
 
55
55
 
56
56
 
@@ -185,4 +185,4 @@ var _chunkQ7TUNJD4cjs = require('./chunk-Q7TUNJD4.cjs');
185
185
 
186
186
 
187
187
 
188
- exports.DATETIME_PATTERNS = _chunk53EEWALQcjs.DATETIME_PATTERNS; exports.ID_PATTERNS = _chunkJZEF5Q3Wcjs.ID_PATTERNS; exports.TAIWAN_BANK_CODES = _chunkQQWX3ICKcjs.TAIWAN_BANK_CODES; exports.TIME_PATTERNS = _chunkEDTNS2XLcjs.TIME_PATTERNS; exports.VALID_3_DIGIT_PREFIXES = _chunkFP4O2ICMcjs.VALID_3_DIGIT_PREFIXES; exports.boolean = _chunkLNWEJED7cjs.boolean; exports.color = _chunkA2GAEU4Ocjs.color; exports.coordinate = _chunkFEL432I2cjs.coordinate; exports.creditCard = _chunkZCX22PY4cjs.creditCard; exports.date = _chunk4AQB4RSUcjs.date; exports.datetime = _chunk53EEWALQcjs.datetime; exports.detectCardType = _chunkZCX22PY4cjs.detectCardType; exports.detectIdType = _chunkJZEF5Q3Wcjs.detectIdType; exports.email = _chunkH25N5GP6cjs.email; exports.file = _chunkKIUO2HIRcjs.file; exports.getLocale = _chunkQ7TUNJD4cjs.getLocale; exports.id = _chunkJZEF5Q3Wcjs.id; exports.ip = _chunkLXFRQLH4cjs.ip; exports.manyOf = _chunk5U5ERV2Pcjs.manyOf; exports.normalizeDateTimeValue = _chunk53EEWALQcjs.normalizeDateTimeValue; exports.normalizeTime = _chunkEDTNS2XLcjs.normalizeTime; exports.number = _chunkG747FHUZcjs.number; exports.oneOf = _chunk5NBWPAHCcjs.oneOf; exports.parseDateTimeValue = _chunk53EEWALQcjs.parseDateTimeValue; exports.parseTimeToMinutes = _chunkEDTNS2XLcjs.parseTimeToMinutes; exports.password = _chunkQ24GYUTOcjs.password; exports.setLocale = _chunkQ7TUNJD4cjs.setLocale; exports.text = _chunkHZ2WESSLcjs.text; exports.time = _chunkEDTNS2XLcjs.time; exports.twBankAccount = _chunkQQWX3ICKcjs.twBankAccount; exports.twBusinessId = _chunkIWR3H7IHcjs.twBusinessId; exports.twFax = _chunkBZSPJJYTcjs.twFax; exports.twInvoice = _chunkV2KKGSKQcjs.twInvoice; exports.twLicensePlate = _chunkTPXRQT2Hcjs.twLicensePlate; exports.twMobile = _chunkAYCXAJRAcjs.twMobile; exports.twNationalId = _chunkUCPKW43Kcjs.twNationalId; exports.twPassport = _chunk5ZMTAI4Gcjs.twPassport; exports.twPostalCode = _chunkFP4O2ICMcjs.twPostalCode; exports.twTel = _chunkVKBNKPFOcjs.twTel; exports.url = _chunkTDEXEIHHcjs.url; exports.validate3DigitPostalCode = _chunkFP4O2ICMcjs.validate3DigitPostalCode; exports.validate5DigitPostalCode = _chunkFP4O2ICMcjs.validate5DigitPostalCode; exports.validate6DigitPostalCode = _chunkFP4O2ICMcjs.validate6DigitPostalCode; exports.validateCitizenId = _chunkUCPKW43Kcjs.validateCitizenId; exports.validateColor = _chunkA2GAEU4Ocjs.validateColor; exports.validateCreditCard = _chunkZCX22PY4cjs.validateCreditCard; exports.validateDateTimeFormat = _chunk53EEWALQcjs.validateDateTimeFormat; exports.validateIPv4 = _chunkLXFRQLH4cjs.validateIPv4; exports.validateIPv6 = _chunkLXFRQLH4cjs.validateIPv6; exports.validateIdType = _chunkJZEF5Q3Wcjs.validateIdType; exports.validateLatitude = _chunkFEL432I2cjs.validateLatitude; exports.validateLongitude = _chunkFEL432I2cjs.validateLongitude; exports.validateNewResidentId = _chunkUCPKW43Kcjs.validateNewResidentId; exports.validateOldResidentId = _chunkUCPKW43Kcjs.validateOldResidentId; exports.validateTaiwanBankAccount = _chunkQQWX3ICKcjs.validateTaiwanBankAccount; exports.validateTaiwanBusinessId = _chunkIWR3H7IHcjs.validateTaiwanBusinessId; exports.validateTaiwanFax = _chunkBZSPJJYTcjs.validateTaiwanFax; exports.validateTaiwanInvoice = _chunkV2KKGSKQcjs.validateTaiwanInvoice; exports.validateTaiwanLicensePlate = _chunkTPXRQT2Hcjs.validateTaiwanLicensePlate; exports.validateTaiwanMobile = _chunkAYCXAJRAcjs.validateTaiwanMobile; exports.validateTaiwanNationalId = _chunkUCPKW43Kcjs.validateTaiwanNationalId; exports.validateTaiwanPassport = _chunk5ZMTAI4Gcjs.validateTaiwanPassport; exports.validateTaiwanPostalCode = _chunkFP4O2ICMcjs.validateTaiwanPostalCode; exports.validateTaiwanTel = _chunkVKBNKPFOcjs.validateTaiwanTel; exports.validateTimeFormat = _chunkEDTNS2XLcjs.validateTimeFormat;
188
+ exports.DATETIME_PATTERNS = _chunk53EEWALQcjs.DATETIME_PATTERNS; exports.ID_PATTERNS = _chunkJZEF5Q3Wcjs.ID_PATTERNS; exports.TAIWAN_BANK_CODES = _chunkQQWX3ICKcjs.TAIWAN_BANK_CODES; exports.TIME_PATTERNS = _chunkEDTNS2XLcjs.TIME_PATTERNS; exports.VALID_3_DIGIT_PREFIXES = _chunkFP4O2ICMcjs.VALID_3_DIGIT_PREFIXES; exports.boolean = _chunkLNWEJED7cjs.boolean; exports.color = _chunkA2GAEU4Ocjs.color; exports.coordinate = _chunkFEL432I2cjs.coordinate; exports.creditCard = _chunkZCX22PY4cjs.creditCard; exports.date = _chunk4AQB4RSUcjs.date; exports.datetime = _chunk53EEWALQcjs.datetime; exports.detectCardType = _chunkZCX22PY4cjs.detectCardType; exports.detectIdType = _chunkJZEF5Q3Wcjs.detectIdType; exports.email = _chunkH25N5GP6cjs.email; exports.file = _chunkKIUO2HIRcjs.file; exports.getLocale = _chunkQ7TUNJD4cjs.getLocale; exports.id = _chunkJZEF5Q3Wcjs.id; exports.ip = _chunkLXFRQLH4cjs.ip; exports.manyOf = _chunk5U5ERV2Pcjs.manyOf; exports.normalizeDateTimeValue = _chunk53EEWALQcjs.normalizeDateTimeValue; exports.normalizeTime = _chunkEDTNS2XLcjs.normalizeTime; exports.number = _chunkG747FHUZcjs.number; exports.oneOf = _chunk5NBWPAHCcjs.oneOf; exports.parseDateTimeValue = _chunk53EEWALQcjs.parseDateTimeValue; exports.parseTimeToMinutes = _chunkEDTNS2XLcjs.parseTimeToMinutes; exports.password = _chunkQ24GYUTOcjs.password; exports.setLocale = _chunkQ7TUNJD4cjs.setLocale; exports.text = _chunkHZ2WESSLcjs.text; exports.time = _chunkEDTNS2XLcjs.time; exports.twBankAccount = _chunkQQWX3ICKcjs.twBankAccount; exports.twBusinessId = _chunkIWR3H7IHcjs.twBusinessId; exports.twFax = _chunkBZSPJJYTcjs.twFax; exports.twInvoice = _chunkV2KKGSKQcjs.twInvoice; exports.twLicensePlate = _chunkTPXRQT2Hcjs.twLicensePlate; exports.twMobile = _chunkAYCXAJRAcjs.twMobile; exports.twNationalId = _chunkUCPKW43Kcjs.twNationalId; exports.twPassport = _chunk5ZMTAI4Gcjs.twPassport; exports.twPostalCode = _chunkFP4O2ICMcjs.twPostalCode; exports.twTel = _chunkV2WFT5M2cjs.twTel; exports.url = _chunkTDEXEIHHcjs.url; exports.validate3DigitPostalCode = _chunkFP4O2ICMcjs.validate3DigitPostalCode; exports.validate5DigitPostalCode = _chunkFP4O2ICMcjs.validate5DigitPostalCode; exports.validate6DigitPostalCode = _chunkFP4O2ICMcjs.validate6DigitPostalCode; exports.validateCitizenId = _chunkUCPKW43Kcjs.validateCitizenId; exports.validateColor = _chunkA2GAEU4Ocjs.validateColor; exports.validateCreditCard = _chunkZCX22PY4cjs.validateCreditCard; exports.validateDateTimeFormat = _chunk53EEWALQcjs.validateDateTimeFormat; exports.validateIPv4 = _chunkLXFRQLH4cjs.validateIPv4; exports.validateIPv6 = _chunkLXFRQLH4cjs.validateIPv6; exports.validateIdType = _chunkJZEF5Q3Wcjs.validateIdType; exports.validateLatitude = _chunkFEL432I2cjs.validateLatitude; exports.validateLongitude = _chunkFEL432I2cjs.validateLongitude; exports.validateNewResidentId = _chunkUCPKW43Kcjs.validateNewResidentId; exports.validateOldResidentId = _chunkUCPKW43Kcjs.validateOldResidentId; exports.validateTaiwanBankAccount = _chunkQQWX3ICKcjs.validateTaiwanBankAccount; exports.validateTaiwanBusinessId = _chunkIWR3H7IHcjs.validateTaiwanBusinessId; exports.validateTaiwanFax = _chunkBZSPJJYTcjs.validateTaiwanFax; exports.validateTaiwanInvoice = _chunkV2KKGSKQcjs.validateTaiwanInvoice; exports.validateTaiwanLicensePlate = _chunkTPXRQT2Hcjs.validateTaiwanLicensePlate; exports.validateTaiwanMobile = _chunkAYCXAJRAcjs.validateTaiwanMobile; exports.validateTaiwanNationalId = _chunkUCPKW43Kcjs.validateTaiwanNationalId; exports.validateTaiwanPassport = _chunk5ZMTAI4Gcjs.validateTaiwanPassport; exports.validateTaiwanPostalCode = _chunkFP4O2ICMcjs.validateTaiwanPostalCode; exports.validateTaiwanTel = _chunkV2WFT5M2cjs.validateTaiwanTel; exports.validateTimeFormat = _chunkEDTNS2XLcjs.validateTimeFormat;
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ import {
50
50
  import {
51
51
  twTel,
52
52
  validateTaiwanTel
53
- } from "./chunk-TRQMRHFM.js";
53
+ } from "./chunk-MUXYP6IK.js";
54
54
  import {
55
55
  twFax,
56
56
  validateTaiwanFax
@@ -1,9 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
3
 
4
- var _chunkVKBNKPFOcjs = require('../chunk-VKBNKPFO.cjs');
4
+ var _chunkV2WFT5M2cjs = require('../chunk-V2WFT5M2.cjs');
5
5
  require('../chunk-Q7TUNJD4.cjs');
6
6
 
7
7
 
8
8
 
9
- exports.twTel = _chunkVKBNKPFOcjs.twTel; exports.validateTaiwanTel = _chunkVKBNKPFOcjs.validateTaiwanTel;
9
+ exports.twTel = _chunkV2WFT5M2cjs.twTel; exports.validateTaiwanTel = _chunkV2WFT5M2cjs.validateTaiwanTel;
@@ -71,6 +71,7 @@ type TwTelSchema<IsRequired extends boolean> = IsRequired extends true ? ZodStri
71
71
  * - 06: Tainan - 7 digits
72
72
  * - 07: Kaohsiung - 7-8 digits
73
73
  * - 08: Pingtung - 7 digits
74
+ * - 0700: Premium rate (付費語音資訊) - 6 digits
74
75
  * - 0800: Toll-free - 6 digits
75
76
  * - 0809: Toll-free - 6 digits
76
77
  * - 082: Kinmen - 6 digits
@@ -71,6 +71,7 @@ type TwTelSchema<IsRequired extends boolean> = IsRequired extends true ? ZodStri
71
71
  * - 06: Tainan - 7 digits
72
72
  * - 07: Kaohsiung - 7-8 digits
73
73
  * - 08: Pingtung - 7 digits
74
+ * - 0700: Premium rate (付費語音資訊) - 6 digits
74
75
  * - 0800: Toll-free - 6 digits
75
76
  * - 0809: Toll-free - 6 digits
76
77
  * - 082: Kinmen - 6 digits
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  twTel,
3
3
  validateTaiwanTel
4
- } from "../chunk-TRQMRHFM.js";
4
+ } from "../chunk-MUXYP6IK.js";
5
5
  import "../chunk-POIDES2L.js";
6
6
  export {
7
7
  twTel,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hy_ong/zod-kit",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "A comprehensive TypeScript library providing pre-built Zod validation schemas with full internationalization support for common data types and Taiwan-specific formats",
5
5
  "keywords": [
6
6
  "zod",
@@ -7,7 +7,7 @@
7
7
  * Avoids z.preprocess() to preserve z.input types for React Hook Form compatibility.
8
8
  *
9
9
  * @author Ong Hoe Yuan
10
- * @version 0.2.5
10
+ * @version 0.2.6
11
11
  */
12
12
 
13
13
  import { z, ZodType } from "zod"
@@ -66,7 +66,7 @@ export type ManyOfOptions<IsRequired extends boolean = true, V extends readonly
66
66
  * @template V - The tuple type of allowed values
67
67
  */
68
68
  export type ManyOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true
69
- ? ZodType<V[number][], V[number][] | "" | null | undefined>
69
+ ? ZodType<V[number][], V[number][]>
70
70
  : ZodType<V[number][] | null, V[number][] | "" | null | undefined>
71
71
 
72
72
  /**
@@ -4,11 +4,11 @@
4
4
  * Provides single-select validation that restricts input to a predefined set of allowed values,
5
5
  * with support for case-insensitive matching, default values, and transformation.
6
6
  *
7
- * Uses z.enum() internally to preserve literal type inference for both z.input and z.output,
8
- * making it compatible with React Hook Form resolvers and other type-aware form libraries.
7
+ * When required=true, z.input is narrowed to V[number] (no empty/null/undefined),
8
+ * making it fully compatible with React Hook Form resolvers and type-aware form libraries.
9
9
  *
10
10
  * @author Ong Hoe Yuan
11
- * @version 0.2.5
11
+ * @version 0.2.6
12
12
  */
13
13
 
14
14
  import { z, ZodType } from "zod"
@@ -55,14 +55,14 @@ export type OneOfOptions<IsRequired extends boolean = true, V extends readonly (
55
55
  * @template V - The tuple type of allowed values
56
56
  */
57
57
  export type OneOfSchema<IsRequired extends boolean, V extends readonly (string | number)[]> = IsRequired extends true
58
- ? ZodType<V[number], V[number] | "" | null | undefined>
58
+ ? ZodType<V[number], V[number]>
59
59
  : ZodType<V[number] | null, V[number] | "" | null | undefined>
60
60
 
61
61
  /**
62
62
  * Creates a Zod schema for single-select validation that restricts values to a predefined set
63
63
  *
64
- * Uses z.enum() internally to preserve both z.input and z.output literal types,
65
- * ensuring compatibility with React Hook Form and other type-aware form libraries.
64
+ * When required=true, z.input is narrowed to V[number] only (no empty/null/undefined),
65
+ * ensuring full compatibility with React Hook Form and other type-aware form libraries.
66
66
  *
67
67
  * @template IsRequired - Whether the field is required (affects return type)
68
68
  * @template V - The tuple type of allowed values (inferred via const type parameter)
@@ -75,6 +75,7 @@ export type TwTelSchema<IsRequired extends boolean> = IsRequired extends true ?
75
75
  * - 06: Tainan - 7 digits
76
76
  * - 07: Kaohsiung - 7-8 digits
77
77
  * - 08: Pingtung - 7 digits
78
+ * - 0700: Premium rate (付費語音資訊) - 6 digits
78
79
  * - 0800: Toll-free - 6 digits
79
80
  * - 0809: Toll-free - 6 digits
80
81
  * - 082: Kinmen - 6 digits
@@ -101,6 +102,7 @@ const validateTaiwanTel = (value: string): boolean => {
101
102
  // 06: Tainan - 7 digits
102
103
  // 07: Kaohsiung - 7-8 digits
103
104
  // 08: Pingtung - 7 digits
105
+ // 0700: Premium rate (付費語音資訊) - 6 digits
104
106
  // 0800/0809: Toll-free - 6 digits
105
107
  // 082: Kinmen - 6 digits
106
108
  // 0836: Matsu - 5-6 digits
@@ -116,6 +118,10 @@ const validateTaiwanTel = (value: string): boolean => {
116
118
 
117
119
  // Check 4-digit area codes first
118
120
  const areaCode4 = cleanValue.substring(0, 4)
121
+ if (areaCode4 === "0700") {
122
+ // Premium rate (付費語音資訊): 0700 + 6 digits, total 10 digits
123
+ return cleanValue.length === 10 && /^0700\d{6}$/.test(cleanValue)
124
+ }
119
125
  if (areaCode4 === "0800" || areaCode4 === "0809") {
120
126
  // Toll-free: 0800/0809 + 6 digits, total 10 digits
121
127
  return cleanValue.length === 10 && /^080[09]\d{6}$/.test(cleanValue)
@@ -41,6 +41,10 @@ describe("Taiwan twTel(true) validator", () => {
41
41
  expect(schema.parse("082661234")).toBe("082661234") // 0826-61234 (9 digits, Wuqiu)
42
42
  expect(schema.parse("083621234")).toBe("083621234") // 0836-21234 (9 digits, Matsu)
43
43
 
44
+ // Premium rate numbers
45
+ expect(schema.parse("0700123456")).toBe("0700123456") // 0700-123-456 (10 digits)
46
+ expect(schema.parse("0700-123-456")).toBe("0700-123-456") // with separators
47
+
44
48
  // Toll-free numbers
45
49
  expect(schema.parse("0800123456")).toBe("0800123456") // 0800-123-456 (10 digits)
46
50
  expect(schema.parse("0809123456")).toBe("0809123456") // 0809-123-456 (10 digits)
@@ -256,6 +260,10 @@ describe("Taiwan twTel(true) validator", () => {
256
260
  expect(validateTaiwanTel("083621234")).toBe(true) // Matsu 9 digits
257
261
  expect(validateTaiwanTel("0836212345")).toBe(true) // Matsu 10 digits
258
262
 
263
+ // Premium rate numbers
264
+ expect(validateTaiwanTel("0700123456")).toBe(true) // 0700
265
+ expect(validateTaiwanTel("0700-123-456")).toBe(true) // 0700 with separators
266
+
259
267
  // Toll-free numbers
260
268
  expect(validateTaiwanTel("0800123456")).toBe(true) // 0800
261
269
  expect(validateTaiwanTel("0809123456")).toBe(true) // 0809
@@ -280,6 +288,8 @@ describe("Taiwan twTel(true) validator", () => {
280
288
  expect(validateTaiwanTel("071234567")).toBe(false) // Invalid first digit for 07
281
289
  expect(validateTaiwanTel("037134567")).toBe(false) // Invalid first digit for 037
282
290
  expect(validateTaiwanTel("081234567")).toBe(false) // Invalid first digit for 08
291
+ expect(validateTaiwanTel("070012345")).toBe(false) // 0700 too short (9 digits)
292
+ expect(validateTaiwanTel("07001234567")).toBe(false) // 0700 too long (11 digits)
283
293
  expect(validateTaiwanTel("080012345")).toBe(false) // 0800 too short (9 digits)
284
294
  expect(validateTaiwanTel("08001234567")).toBe(false) // 0800 too long (11 digits)
285
295
  expect(validateTaiwanTel("0801123456")).toBe(false) // 0801 not valid toll-free prefix
@@ -380,6 +390,7 @@ describe("Taiwan twTel(true) validator", () => {
380
390
  { code: "08", numbers: ["084234567"] }, // Pingtung (9 digits, first digit 4) - from utility test ✓
381
391
  { code: "082", numbers: ["082234567"] }, // Kinmen (9 digits, first digit 2) - from utility test ✓
382
392
  { code: "089", numbers: ["089234567"] }, // Taitung (9 digits, first digit 2) - from utility test ✓
393
+ { code: "0700", numbers: ["0700123456"] }, // Premium rate (10 digits)
383
394
  { code: "0800", numbers: ["0800123456"] }, // Toll-free (10 digits)
384
395
  { code: "0809", numbers: ["0809123456"] }, // Toll-free (10 digits)
385
396
  { code: "0826", numbers: ["082661234"] }, // Wuqiu (9 digits, first digit 6) - from utility test ✓