diff --git a/packages/contracts/package.json b/packages/contracts/package.json index a200ed1f..1d917e66 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -35,7 +35,7 @@ "size-limit": [ { "path": "./dist/contracts.js", - "limit": "774 B" + "limit": "829 B" } ] } diff --git a/packages/contracts/src/contracts.test.ts b/packages/contracts/src/contracts.test.ts index 4613be63..faa9e5aa 100644 --- a/packages/contracts/src/contracts.test.ts +++ b/packages/contracts/src/contracts.test.ts @@ -12,6 +12,7 @@ import { tuple, type Contract, nothing, + anything, } from './index'; describe('bool', () => { @@ -625,3 +626,37 @@ describe('nothing', () => { `); }); }); + +describe('anything', () => { + it('accepts any field', () => { + const cntrct = obj({ key: anything }); + + expect(cntrct.isData({})).toBeTruthy(); + expect(cntrct.getErrorMessages({})).toEqual([]); + + expect(cntrct.isData({ key: 1 })).toBeTruthy(); + expect(cntrct.getErrorMessages({ key: 1 })).toEqual([]); + + expect(cntrct.isData({ key: null })).toBeTruthy(); + expect(cntrct.getErrorMessages({ key: null })).toEqual([]); + + expect(cntrct.isData({ key: undefined })).toBeTruthy(); + expect(cntrct.getErrorMessages({ key: undefined })).toEqual([]); + }); + + it('does not break original', () => { + const cntrct = obj({ key: or(num, anything) }); + + expect(cntrct.isData({ key: 1 })).toBeTruthy(); + expect(cntrct.getErrorMessages({ key: 1 })).toEqual([]); + + expect(cntrct.isData({ key: null })).toBeTruthy(); + expect(cntrct.getErrorMessages({ key: null })).toEqual([]); + + expect(cntrct.isData({ key: undefined })).toBeTruthy(); + expect(cntrct.getErrorMessages({ key: undefined })).toEqual([]); + + expect(cntrct.isData({ key: 'a' })).toBeTruthy(); + expect(cntrct.getErrorMessages({ key: 'a' })).toEqual([]); + }); +}); diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts index 7a967af5..f29b52bd 100644 --- a/packages/contracts/src/index.ts +++ b/packages/contracts/src/index.ts @@ -396,6 +396,25 @@ export function tuple(...contracts: Array>): any { */ export const nothing = or(val(null), val(undefined)); +/** + * _Contract_ that allows any value, basically a no-op. + * + * @since v1.1.0 + * + * @example + * + * anything.isData('hello') === true; + * anything.isData(42) === true; + * anything.isData({}) === true; + * anything.isData([]) === true; + * anything.isData(null) === true; + * anything.isData(undefined) === true; + */ +export const anything: Contract = { + isData: (x): x is unknown => true, + getErrorMessages: () => [], +}; + // -- utils function createSimpleContract(exepctedType: string): Contract {