@@ -35,13 +35,17 @@ const examples = {
3535 boolean : [ true , false ] ,
3636 array : [ [ ] , [ 0 , 1 , 2 ] , [ "a" , "b" , "c" ] , [ 0 , "a" , true ] ] ,
3737 record : [ { } , { a : 0 , b : 1 , c : 2 } , { a : "a" , b : "b" , c : "c" } ] ,
38- function : [ function ( ) { } ] ,
38+ function : [ function a ( ) { } , ( ) => { } ] ,
3939 null : [ null ] ,
4040 undefined : [ undefined ] ,
4141 symbol : [ Symbol ( "a" ) , Symbol ( "b" ) , Symbol ( "c" ) ] ,
42- } ;
42+ date : [ new Date ( 1690248225000 ) , new Date ( 0 ) ] ,
43+ promise : [ new Promise ( ( ) => { } ) ] ,
44+ } as const ;
4345
4446function stringify ( x : unknown ) : string {
47+ if ( x instanceof Date ) return `Date(${ x . valueOf ( ) } )` ;
48+ if ( x instanceof Promise ) return "Promise" ;
4549 if ( typeof x === "function" ) return x . toString ( ) ;
4650 if ( typeof x === "bigint" ) return `${ x } n` ;
4751 if ( typeof x === "symbol" ) return x . toString ( ) ;
@@ -51,10 +55,18 @@ function stringify(x: unknown): string {
5155async function testWithExamples < T > (
5256 t : Deno . TestContext ,
5357 pred : Predicate < T > ,
54- validExamples : ( keyof typeof examples ) [ ] ,
58+ opts ?: {
59+ validExamples ?: ( keyof typeof examples ) [ ] ;
60+ excludeExamples ?: ( keyof typeof examples ) [ ] ;
61+ } ,
5562) : Promise < void > {
56- for ( const [ name , example ] of Object . entries ( examples ) ) {
57- const expect = validExamples . includes ( name as keyof typeof examples ) ;
63+ const { validExamples = [ ] , excludeExamples = [ ] } = opts ?? { } ;
64+ const exampleEntries = ( Object . entries ( examples ) as unknown as [
65+ name : keyof typeof examples ,
66+ example : unknown [ ] ,
67+ ] [ ] ) . filter ( ( [ k ] ) => ! excludeExamples . includes ( k ) ) ;
68+ for ( const [ name , example ] of exampleEntries ) {
69+ const expect = validExamples . includes ( name ) ;
5870 for ( const v of example ) {
5971 await t . step (
6072 `returns ${ expect } on ${ stringify ( v ) } ` ,
@@ -67,23 +79,23 @@ async function testWithExamples<T>(
6779}
6880
6981Deno . test ( "isString" , async ( t ) => {
70- await testWithExamples ( t , isString , [ "string" ] ) ;
82+ await testWithExamples ( t , isString , { validExamples : [ "string" ] } ) ;
7183} ) ;
7284
7385Deno . test ( "isNumber" , async ( t ) => {
74- await testWithExamples ( t , isNumber , [ "number" ] ) ;
86+ await testWithExamples ( t , isNumber , { validExamples : [ "number" ] } ) ;
7587} ) ;
7688
7789Deno . test ( "isBigInt" , async ( t ) => {
78- await testWithExamples ( t , isBigInt , [ "bigint" ] ) ;
90+ await testWithExamples ( t , isBigInt , { validExamples : [ "bigint" ] } ) ;
7991} ) ;
8092
8193Deno . test ( "isBoolean" , async ( t ) => {
82- await testWithExamples ( t , isBoolean , [ "boolean" ] ) ;
94+ await testWithExamples ( t , isBoolean , { validExamples : [ "boolean" ] } ) ;
8395} ) ;
8496
8597Deno . test ( "isArray" , async ( t ) => {
86- await testWithExamples ( t , isArray , [ "array" ] ) ;
98+ await testWithExamples ( t , isArray , { validExamples : [ "array" ] } ) ;
8799} ) ;
88100
89101Deno . test ( "isArrayOf<T>" , async ( t ) => {
@@ -103,6 +115,9 @@ Deno.test("isArrayOf<T>", async (t) => {
103115 assertEquals ( isArrayOf ( isNumber ) ( [ "a" , "b" , "c" ] ) , false ) ;
104116 assertEquals ( isArrayOf ( isString ) ( [ true , false , true ] ) , false ) ;
105117 } ) ;
118+ await testWithExamples ( t , isArrayOf ( ( _ : unknown ) : _ is unknown => true ) , {
119+ excludeExamples : [ "array" ] ,
120+ } ) ;
106121} ) ;
107122
108123Deno . test ( "isTupleOf<T>" , async ( t ) => {
@@ -118,12 +133,21 @@ Deno.test("isTupleOf<T>", async (t) => {
118133 await t . step ( "returns true on T tuple" , ( ) => {
119134 const predTup = [ isNumber , isString , isBoolean ] as const ;
120135 assertEquals ( isTupleOf ( predTup ) ( [ 0 , "a" , true ] ) , true ) ;
136+ assertEquals ( isTupleOf ( [ ] ) ( [ ] ) , true , "Specify empty predicates" ) ;
121137 } ) ;
122138 await t . step ( "returns false on non T tuple" , ( ) => {
123139 const predTup = [ isNumber , isString , isBoolean ] as const ;
124140 assertEquals ( isTupleOf ( predTup ) ( [ 0 , 1 , 2 ] ) , false ) ;
125141 assertEquals ( isTupleOf ( predTup ) ( [ 0 , "a" ] ) , false ) ;
126142 assertEquals ( isTupleOf ( predTup ) ( [ 0 , "a" , true , 0 ] ) , false ) ;
143+ assertEquals (
144+ isTupleOf ( [ ] ) ( [ 0 ] ) ,
145+ false ,
146+ "Specify empty predicates and value has entry" ,
147+ ) ;
148+ } ) ;
149+ await testWithExamples ( t , isTupleOf ( [ ( _ : unknown ) : _ is unknown => true ] ) , {
150+ excludeExamples : [ "array" ] ,
127151 } ) ;
128152} ) ;
129153
@@ -154,10 +178,15 @@ Deno.test("isUniformTupleOf<T>", async (t) => {
154178 assertEquals ( isUniformTupleOf ( 4 ) ( [ 0 , 1 , 2 , 3 , 4 ] ) , false ) ;
155179 assertEquals ( isUniformTupleOf ( 3 , is . Number ) ( [ "a" , "b" , "c" ] ) , false ) ;
156180 } ) ;
181+ await testWithExamples ( t , isUniformTupleOf ( 4 ) , {
182+ excludeExamples : [ "array" ] ,
183+ } ) ;
157184} ) ;
158185
159186Deno . test ( "isRecord" , async ( t ) => {
160- await testWithExamples ( t , isRecord , [ "record" ] ) ;
187+ await testWithExamples ( t , isRecord , {
188+ validExamples : [ "record" , "date" , "promise" ] ,
189+ } ) ;
161190} ) ;
162191
163192Deno . test ( "isRecordOf<T>" , async ( t ) => {
@@ -179,6 +208,9 @@ Deno.test("isRecordOf<T>", async (t) => {
179208 assertEquals ( isRecordOf ( isNumber ) ( { a : "a" } ) , false ) ;
180209 assertEquals ( isRecordOf ( isString ) ( { a : true } ) , false ) ;
181210 } ) ;
211+ await testWithExamples ( t , isRecordOf ( ( _ : unknown ) : _ is unknown => true ) , {
212+ excludeExamples : [ "record" , "date" , "promise" ] ,
213+ } ) ;
182214} ) ;
183215
184216Deno . test ( "isObjectOf<T>" , async ( t ) => {
@@ -225,10 +257,15 @@ Deno.test("isObjectOf<T>", async (t) => {
225257 false ,
226258 ) ;
227259 } ) ;
260+ await testWithExamples (
261+ t ,
262+ isObjectOf ( { a : ( _ : unknown ) : _ is unknown => true } ) ,
263+ { excludeExamples : [ "record" ] } ,
264+ ) ;
228265} ) ;
229266
230267Deno . test ( "isFunction" , async ( t ) => {
231- await testWithExamples ( t , isFunction , [ "function" ] ) ;
268+ await testWithExamples ( t , isFunction , { validExamples : [ "function" ] } ) ;
232269} ) ;
233270
234271Deno . test ( "isInstanceOf<T>" , async ( t ) => {
@@ -238,19 +275,17 @@ Deno.test("isInstanceOf<T>", async (t) => {
238275 assertEquals ( isInstanceOf ( Date ) ( new Date ( ) ) , true ) ;
239276 assertEquals ( isInstanceOf ( Promise < string > ) ( new Promise ( ( ) => { } ) ) , true ) ;
240277 } ) ;
241- await t . step ( "returns false on non function " , ( ) => {
278+ await t . step ( "with user-defined class " , async ( t ) => {
242279 class Cls { }
243- assertEquals ( isInstanceOf ( Cls ) ( new Date ( ) ) , false ) ;
244- assertEquals ( isInstanceOf ( Cls ) ( new Promise ( ( ) => { } ) ) , false ) ;
245- assertEquals ( isInstanceOf ( Cls ) ( "" ) , false ) ;
246- assertEquals ( isInstanceOf ( Cls ) ( 0 ) , false ) ;
247- assertEquals ( isInstanceOf ( Cls ) ( true ) , false ) ;
248- assertEquals ( isInstanceOf ( Cls ) ( false ) , false ) ;
249- assertEquals ( isInstanceOf ( Cls ) ( [ ] ) , false ) ;
250- assertEquals ( isInstanceOf ( Cls ) ( { } ) , false ) ;
251- assertEquals ( isInstanceOf ( Cls ) ( function ( ) { } ) , false ) ;
252- assertEquals ( isInstanceOf ( Cls ) ( null ) , false ) ;
253- assertEquals ( isInstanceOf ( Cls ) ( undefined ) , false ) ;
280+ await testWithExamples ( t , isInstanceOf ( Cls ) ) ;
281+ } ) ;
282+ await t . step ( "with Date" , async ( t ) => {
283+ await testWithExamples ( t , isInstanceOf ( Date ) , { validExamples : [ "date" ] } ) ;
284+ } ) ;
285+ await t . step ( "with Promise" , async ( t ) => {
286+ await testWithExamples ( t , isInstanceOf ( Promise ) , {
287+ validExamples : [ "promise" ] ,
288+ } ) ;
254289 } ) ;
255290 await t . step ( "returns proper type predicate" , ( ) => {
256291 class Cls { }
@@ -272,19 +307,21 @@ Deno.test("isInstanceOf<T>", async (t) => {
272307} ) ;
273308
274309Deno . test ( "isNull" , async ( t ) => {
275- await testWithExamples ( t , isNull , [ "null" ] ) ;
310+ await testWithExamples ( t , isNull , { validExamples : [ "null" ] } ) ;
276311} ) ;
277312
278313Deno . test ( "isUndefined" , async ( t ) => {
279- await testWithExamples ( t , isUndefined , [ "undefined" ] ) ;
314+ await testWithExamples ( t , isUndefined , { validExamples : [ "undefined" ] } ) ;
280315} ) ;
281316
282317Deno . test ( "isNullish" , async ( t ) => {
283- await testWithExamples ( t , isNullish , [ "null" , "undefined" ] ) ;
318+ await testWithExamples ( t , isNullish , {
319+ validExamples : [ "null" , "undefined" ] ,
320+ } ) ;
284321} ) ;
285322
286323Deno . test ( "isSymbol" , async ( t ) => {
287- await testWithExamples ( t , isSymbol , [ "symbol" ] ) ;
324+ await testWithExamples ( t , isSymbol , { validExamples : [ "symbol" ] } ) ;
288325} ) ;
289326
290327Deno . test ( "isOneOf<T>" , async ( t ) => {
@@ -301,13 +338,11 @@ Deno.test("isOneOf<T>", async (t) => {
301338 assertEquals ( isOneOf ( preds ) ( "a" ) , true ) ;
302339 assertEquals ( isOneOf ( preds ) ( true ) , true ) ;
303340 } ) ;
304- await t . step ( "returns false on non of T" , ( ) => {
341+ await t . step ( "returns false on non of T" , async ( t ) => {
305342 const preds = [ isNumber , isString , isBoolean ] ;
306- assertEquals ( isOneOf ( preds ) ( [ ] ) , false ) ;
307- assertEquals ( isOneOf ( preds ) ( { } ) , false ) ;
308- assertEquals ( isOneOf ( preds ) ( function ( ) { } ) , false ) ;
309- assertEquals ( isOneOf ( preds ) ( null ) , false ) ;
310- assertEquals ( isOneOf ( preds ) ( undefined ) , false ) ;
343+ await testWithExamples ( t , isOneOf ( preds ) , {
344+ excludeExamples : [ "number" , "string" , "boolean" ] ,
345+ } ) ;
311346 } ) ;
312347} ) ;
313348
0 commit comments