@@ -189,7 +189,7 @@ export function isArrayOf<T>(
189189 * // type A = [string, number];
190190 * ```
191191 */
192- export type TupleOf < T extends readonly Predicate < unknown > [ ] > = {
192+ export type TupleOf < T > = {
193193 - readonly [ P in keyof T ] : T [ P ] extends Predicate < infer U > ? U : never ;
194194} ;
195195
@@ -204,37 +204,33 @@ export type TupleOf<T extends readonly Predicate<unknown>[]> = {
204204 * // type A = readonly [string, number];
205205 * ```
206206 */
207- export type ReadonlyTupleOf < T extends readonly Predicate < unknown > [ ] > = {
207+ export type ReadonlyTupleOf < T > = {
208208 [ P in keyof T ] : T [ P ] extends Predicate < infer U > ? U : never ;
209209} ;
210210
211211/**
212- * Return a type predicate function that returns `true` if the type of `x` is `TupleOf<T>`.
212+ * Return a type predicate function that returns `true` if the type of `x` is `TupleOf<T>` or `TupleOf<T, E>` .
213213 *
214214 * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost.
215215 *
216216 * ```ts
217217 * import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
218218 *
219- * const isMyType = is.TupleOf([is.Number, is.String, is.Boolean] as const );
219+ * const isMyType = is.TupleOf([is.Number, is.String, is.Boolean]);
220220 * const a: unknown = [0, "a", true];
221221 * if (isMyType(a)) {
222222 * // a is narrowed to [number, string, boolean]
223223 * const _: [number, string, boolean] = a;
224224 * }
225225 * ```
226226 *
227- * Note that `predTup` must be `readonly` (`as const`) to infer the type of `a` correctly.
228- * TypeScript won't argues if `predTup` is not `readonly` because of its design limitation.
229- * https://github.com/microsoft/TypeScript/issues/34274#issuecomment-541691353
230- *
231- * It can also be used to check the type of the rest of the tuple like:
227+ * With `predElse`:
232228 *
233229 * ```ts
234230 * import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
235231 *
236232 * const isMyType = is.TupleOf(
237- * [is.Number, is.String, is.Boolean] as const ,
233+ * [is.Number, is.String, is.Boolean],
238234 * is.ArrayOf(is.Number),
239235 * );
240236 * const a: unknown = [0, "a", true, 0, 1, 2];
@@ -243,33 +239,44 @@ export type ReadonlyTupleOf<T extends readonly Predicate<unknown>[]> = {
243239 * const _: [number, string, boolean, ...number[]] = a;
244240 * }
245241 * ```
242+ *
243+ * Depending on the version of TypeScript and how values are provided, it may be necessary to add `as const` to the array
244+ * used as `predTup`. If a type error occurs, try adding `as const` as follows:
245+ *
246+ * ```ts
247+ * import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
248+ *
249+ * const predTup = [is.Number, is.String, is.Boolean] as const;
250+ * const isMyType = is.TupleOf(predTup);
251+ * const a: unknown = [0, "a", true];
252+ * if (isMyType(a)) {
253+ * // a is narrowed to [number, string, boolean]
254+ * const _: [number, string, boolean] = a;
255+ * }
256+ * ```
246257 */
247258export function isTupleOf <
248- T extends readonly Predicate < unknown > [ ] ,
249- R extends TupleOf < T > ,
259+ T extends readonly [ Predicate < unknown > , ...Predicate < unknown > [ ] ] ,
250260> (
251261 predTup : T ,
252- ) : Predicate < R > ;
262+ ) : Predicate < TupleOf < T > > ;
253263export function isTupleOf <
254- T extends readonly Predicate < unknown > [ ] ,
264+ T extends readonly [ Predicate < unknown > , ... Predicate < unknown > [ ] ] ,
255265 E extends Predicate < unknown [ ] > ,
256- R extends [ ...TupleOf < T > , ...PredicateType < E > ] ,
257266> (
258267 predTup : T ,
259268 predElse : E ,
260- ) : Predicate < R > ;
269+ ) : Predicate < [ ... TupleOf < T > , ... PredicateType < E > ] > ;
261270export function isTupleOf <
262- T extends readonly Predicate < unknown > [ ] ,
271+ T extends readonly [ Predicate < unknown > , ... Predicate < unknown > [ ] ] ,
263272 E extends Predicate < unknown [ ] > ,
264- R1 extends TupleOf < T > ,
265- R2 extends [ ...TupleOf < T > , ...PredicateType < E > ] ,
266273> (
267274 predTup : T ,
268275 predElse ?: E ,
269- ) : Predicate < R1 | R2 > {
276+ ) : Predicate < TupleOf < T > | [ ... TupleOf < T > , ... PredicateType < E > ] > {
270277 if ( ! predElse ) {
271278 return Object . defineProperties (
272- ( x : unknown ) : x is R1 => {
279+ ( x : unknown ) : x is TupleOf < T > => {
273280 if ( ! isArray ( x ) || x . length !== predTup . length ) {
274281 return false ;
275282 }
@@ -283,7 +290,7 @@ export function isTupleOf<
283290 ) ;
284291 } else {
285292 return Object . defineProperties (
286- ( x : unknown ) : x is R2 => {
293+ ( x : unknown ) : x is [ ... TupleOf < T > , ... PredicateType < E > ] => {
287294 if ( ! isArray ( x ) || x . length < predTup . length ) {
288295 return false ;
289296 }
@@ -308,59 +315,69 @@ export function isTupleOf<
308315 * ```ts
309316 * import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
310317 *
311- * const isMyType = is.ReadonlyTupleOf([is.Number, is.String, is.Boolean] as const );
318+ * const isMyType = is.ReadonlyTupleOf([is.Number, is.String, is.Boolean]);
312319 * const a: unknown = [0, "a", true];
313320 * if (isMyType(a)) {
314321 * // a is narrowed to readonly [number, string, boolean]
315322 * const _: readonly [number, string, boolean] = a;
316323 * }
317324 * ```
318325 *
319- * Note that `predTup` must be `readonly` (`as const`) to infer the type of `a` correctly.
320- * TypeScript won't argues if `predTup` is not `readonly` because of its design limitation.
321- * https://github.com/microsoft/TypeScript/issues/34274#issuecomment-541691353
322- *
323- * It can also be used to check the type of the rest of the tuple like:
326+ * With `predElse`:
324327 *
325328 * ```ts
326329 * import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
327330 *
328331 * const isMyType = is.ReadonlyTupleOf(
329- * [is.Number, is.String, is.Boolean] as const ,
332+ * [is.Number, is.String, is.Boolean],
330333 * is.ArrayOf(is.Number),
331334 * );
332335 * const a: unknown = [0, "a", true, 0, 1, 2];
333336 * if (isMyType(a)) {
334337 * // a is narrowed to readonly [number, string, boolean, ...number[]]
335338 * const _: readonly [number, string, boolean, ...number[]] = a;
336339 * }
340+ * ```
341+ *
342+ * Depending on the version of TypeScript and how values are provided, it may be necessary to add `as const` to the array
343+ * used as `predTup`. If a type error occurs, try adding `as const` as follows:
344+ *
345+ * ```ts
346+ * import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
347+ *
348+ * const predTup = [is.Number, is.String, is.Boolean] as const;
349+ * const isMyType = is.ReadonlyTupleOf(predTup);
350+ * const a: unknown = [0, "a", true];
351+ * if (isMyType(a)) {
352+ * // a is narrowed to readonly [number, string, boolean]
353+ * const _: readonly [number, string, boolean] = a;
354+ * }
355+ * ```
337356 */
338357export function isReadonlyTupleOf <
339- T extends readonly Predicate < unknown > [ ] ,
340- R extends ReadonlyTupleOf < T > ,
358+ T extends readonly [ Predicate < unknown > , ...Predicate < unknown > [ ] ] ,
341359> (
342360 predTup : T ,
343- ) : Predicate < R > ;
361+ ) : Predicate < ReadonlyTupleOf < T > > ;
344362export function isReadonlyTupleOf <
345- T extends readonly Predicate < unknown > [ ] ,
363+ T extends readonly [ Predicate < unknown > , ... Predicate < unknown > [ ] ] ,
346364 E extends Predicate < unknown [ ] > ,
347- R extends readonly [ ...ReadonlyTupleOf < T > , ...PredicateType < E > ] ,
348365> (
349366 predTup : T ,
350367 predElse : E ,
351- ) : Predicate < R > ;
368+ ) : Predicate < readonly [ ... ReadonlyTupleOf < T > , ... PredicateType < E > ] > ;
352369export function isReadonlyTupleOf <
353- T extends readonly Predicate < unknown > [ ] ,
370+ T extends readonly [ Predicate < unknown > , ... Predicate < unknown > [ ] ] ,
354371 E extends Predicate < unknown [ ] > ,
355- R1 extends ReadonlyTupleOf < T > ,
356- R2 extends readonly [ ...ReadonlyTupleOf < T > , ...PredicateType < E > ] ,
357372> (
358373 predTup : T ,
359374 predElse ?: E ,
360- ) : Predicate < R1 | R2 > {
375+ ) : Predicate <
376+ ReadonlyTupleOf < T > | readonly [ ...ReadonlyTupleOf < T > , ...PredicateType < E > ]
377+ > {
361378 if ( ! predElse ) {
362379 return Object . defineProperties (
363- isTupleOf ( predTup ) as Predicate < R1 > ,
380+ isTupleOf ( predTup ) as Predicate < ReadonlyTupleOf < T > > ,
364381 {
365382 name : {
366383 get : ( ) => `isReadonlyTupleOf(${ inspect ( predTup ) } )` ,
@@ -369,7 +386,9 @@ export function isReadonlyTupleOf<
369386 ) ;
370387 } else {
371388 return Object . defineProperties (
372- isTupleOf ( predTup , predElse ) as unknown as Predicate < R2 > ,
389+ isTupleOf ( predTup , predElse ) as unknown as Predicate <
390+ readonly [ ...ReadonlyTupleOf < T > , ...PredicateType < E > ]
391+ > ,
373392 {
374393 name : {
375394 get : ( ) =>
@@ -449,9 +468,13 @@ export function isUniformTupleOf<T, N extends number>(
449468 n : N ,
450469 pred : Predicate < T > = isAny ,
451470) : Predicate < UniformTupleOf < T , N > > {
452- const predInner = isTupleOf ( Array ( n ) . fill ( pred ) ) ;
453471 return Object . defineProperties (
454- ( x : unknown ) : x is UniformTupleOf < T , N > => predInner ( x ) ,
472+ ( x : unknown ) : x is UniformTupleOf < T , N > => {
473+ if ( ! isArray ( x ) || x . length !== n ) {
474+ return false ;
475+ }
476+ return x . every ( ( v ) => pred ( v ) ) ;
477+ } ,
455478 {
456479 name : {
457480 get : ( ) => `isUniformTupleOf(${ n } , ${ inspect ( pred ) } )` ,
0 commit comments