Overview
Version 2.0 of filter-def introduced breaking changes to simplify the API and improve type safety. This guide will help you migrate your existing v1 code to v2.
Breaking Changes
Type Name Changes
The most significant changes in v2 are type naming simplifications:
All public-facing type names were simplified in v2 for better developer experience.
v1 Type v2 Type Description PredicateCreatorFilterMain filter function type InputForPredicateCreator<T>FilterInput<T>Type for filter inputs
Before (v1):
import { inMemoryFilter } from "@filter-def/in-memory" ;
import type { InputForPredicateCreator } from "@filter-def/in-memory" ;
const userFilter = inMemoryFilter < User >(). def ({
name: { kind: "eq" },
minAge: { kind: "gte" , field: "age" },
});
// Type extraction in v1
type UserFilterInput = InputForPredicateCreator < typeof userFilter >;
After (v2):
import { inMemoryFilter } from "@filter-def/in-memory" ;
import type { InMemoryFilterInput } from "@filter-def/in-memory" ;
const userFilter = inMemoryFilter < User >(). def ({
name: { kind: "eq" },
minAge: { kind: "gte" , field: "age" },
});
// Type extraction in v2
type UserFilterInput = InMemoryFilterInput < typeof userFilter >;
Adapter-Specific Type Names
Each adapter now exports its own input type utility:
import type { InMemoryFilterInput } from "@filter-def/in-memory" ;
const userFilter = inMemoryFilter < User >(). def ({ /* ... */ });
type UserInput = InMemoryFilterInput < typeof userFilter >;
Null and Undefined Handling
In v2.0, filter inputs no longer accept null or undefined as explicit values for better type safety:
Before (v1):
// This was allowed in v1
const where = userFilter ({
name: null , // Accepted but confusing behavior
});
After (v2):
// In v2, null/undefined inputs are type errors
const where = userFilter ({
// name: null, // ❌ Type error in v2
});
// Simply omit the field instead
const where = userFilter ({
// Empty object or omit undefined fields
});
If you need to check for null values, use the isNull or isNotNull filter kinds instead of passing null as a filter value.
Migration Steps
Update Package Versions
Update all filter-def packages to v2 in your package.json: pnpm update @filter-def/core @filter-def/in-memory @filter-def/drizzle @filter-def/bigquery
Or manually: {
"dependencies" : {
"@filter-def/in-memory" : "^2.0.0" ,
"@filter-def/drizzle" : "^2.0.0" ,
"@filter-def/bigquery" : "^2.0.0"
}
}
Update Type Imports
Find and replace all type imports: // Find:
import type { InputForPredicateCreator } from "@filter-def/in-memory" ;
// Replace with:
import type { InMemoryFilterInput } from "@filter-def/in-memory" ;
For Drizzle: // Find:
import type { InputForPredicateCreator } from "@filter-def/drizzle" ;
// Replace with:
import type { DrizzleFilterInput } from "@filter-def/drizzle" ;
For BigQuery: // Find:
import type { InputForPredicateCreator } from "@filter-def/bigquery" ;
// Replace with:
import type { BigQueryFilterInput } from "@filter-def/bigquery" ;
Update Type Aliases
Update all type alias definitions: // Before (v1)
type UserFilterInput = InputForPredicateCreator < typeof userFilter >;
// After (v2)
type UserFilterInput = InMemoryFilterInput < typeof userFilter >;
// or DrizzleFilterInput / BigQueryFilterInput depending on adapter
Remove Null Filter Values
Search for any code passing null or undefined as filter values and remove them: // Before (v1)
const results = users . filter (
userFilter ({
name: searchTerm ?? null , // Remove null fallback
minAge: ageFilter ?? undefined , // Remove undefined fallback
})
);
// After (v2)
const filterInput : Partial < UserFilterInput > = {};
if ( searchTerm ) filterInput . name = searchTerm ;
if ( ageFilter ) filterInput . minAge = ageFilter ;
const results = users . filter ( userFilter ( filterInput ));
// Or use object spreading
const results = users . filter (
userFilter ({
... ( searchTerm && { name: searchTerm }),
... ( ageFilter && { minAge: ageFilter }),
})
);
Test Your Changes
Run your type checker and tests: Fix any type errors that appear. Most errors will be related to:
Old type names that need updating
Null/undefined values being passed to filters
New Features in v2
While migrating, consider adopting these new v2 features:
Nested Field Support
v2 adds support for nested field paths in @filter-def/in-memory and @filter-def/bigquery:
interface Employee {
name : { first : string ; last : string };
address : { city : string ; geo : { lat : number ; lng : number } };
}
const employeeFilter = inMemoryFilter < Employee >(). def ({
firstName: { kind: "eq" , field: "name.first" },
city: { kind: "contains" , field: "address.city" },
minLat: { kind: "gte" , field: "address.geo.lat" },
});
const results = employees . filter (
employeeFilter ({
firstName: "John" ,
city: "New York" ,
minLat: 40.7 ,
})
);
Nested fields are not supported in @filter-def/drizzle as Drizzle operates on flat table columns.
Case-Insensitive Contains
The contains filter now supports case-insensitive matching:
const userFilter = inMemoryFilter < User >(). def ({
emailContains: {
kind: "contains" ,
field: "email" ,
caseInsensitive: true , // New in v2
},
});
const results = users . filter (
userFilter ({
emailContains: "EXAMPLE" , // Matches "example", "Example", "EXAMPLE", etc.
})
);
Troubleshooting
Type Errors After Migration
Error: Cannot find name 'InputForPredicateCreator'
Error: Type 'null' is not assignable to type 'string | undefined'
v2 no longer accepts null as a filter value. Instead of: userFilter ({ name: null })
Either omit the field or use the isNull filter: // Option 1: Omit the field
userFilter ({})
// Option 2: Use isNull filter
const userFilter = inMemoryFilter < User >(). def ({
nameIsNull: { kind: "isNull" , field: "name" },
});
userFilter ({ nameIsNull: true })
Error: Property 'PredicateCreator' does not exist
The PredicateCreator type was renamed to adapter-specific filter types. Replace: import type { PredicateCreator } from "@filter-def/in-memory" ;
type MyFilter = PredicateCreator < User , any >;
With: import type { InMemoryFilter } from "@filter-def/in-memory" ;
type MyFilter = InMemoryFilter < User , any >;
Need Help?
If you encounter issues during migration:
Check the GitHub issues for similar problems
Review the API Reference for detailed type information
Open a new issue with your migration question
Upgrade Checklist
Use this checklist to ensure a complete migration: