PredicateBuilder where clause issue - predicatebuilder

I am using PredicateBuilder to generate where clause
var locationFilter = PredicateBuilder.True<dbCompanyLocation>();
locationFilter = locationFilter.And(s => s.IsPrimary == true && s.State == practiceState);
var companyPredicate = PredicateBuilder.True<dbCompany>();
companyPredicate = companyPredicate.And(c => c.dbCompanyLocations.Where(locationFilter));
I am getting following error, Any one can help for this or am i doing something wrong.
Instance argument: cannot convert from 'System.Data.Linq.EntitySet' to 'System.Linq.IQueryable'

The immediate problem seems to be that dbCompany.dbCompanyLocations is an EntitySet, which implements IEnumerable<T> rather than IQueryable<T>. This means its Where extension method expects a Func<dbCompanyLocation, bool>, however the locationFilter variable you are providing is an Expression<Func<dbCompanyLocation, bool>>.
You can create a Func<dbCompanyLocation, bool> from locationFilter by calling the Compile method.
Another problem however is that even if it did type check, c => c.dbCompanyLocations.Where(locationFilter) is not a predicate, since Where returns an IEnumerable<T> instead of a bool. You probably meant to use Any instead of Where i.e.
companyPredicate = companyPredicate.And(c => c.dbCompanyLocations.Any(locationFilter.Compile()));

Related

Type check with typeof === custom type with Flow error

Given the following code:
type CustomTypeA = {
x: number,
y: number,
}
type CustomTypeB = CustomTypeA & {
z: number,
}
type CustomType = CustomTypeA | CustomTypeB
export const myFunction = (a: CustomType | number): number | void => {
if (typeof a === 'number') {
return a; // THIS WORKS WELL, it's considered number after the check, which is correct
} else if (typeof a === CustomType) {
const newX = a.x // ERR: Flow: Cannot get `a.x` because property `x` is missing in `Number`
const newZ = a.z // SAME ERR, Flow: Cannot get `a.z` because property `z` is missing in `Number`.
}
}
Also, the typeof a === CustomType check is highlighted as an error as well:
Flow: Cannot reference type `CustomType` from a value position.
This however doesn't happen for the typeof a === 'number' one.
It's like the check against the custom object type I created is not valid/recognized.
Can someone explain why and possibly how to escape this?
Thanks.
Flow custom types are not values, they do not exist, they vanish after transpilation, therefore you can not use them with a JS operator like typeof because it requires a value. So when you do typeof a === CustomType it will fail, because after compilation you will end with typeof a === , CustomType is just stripped out and you end with invalid JS.
This seems to be a flow limitation to be honest.
There is the %checks operator which allows you to build type guard functions.
One may think you can use this feature to build a type refinement for your custom types with a function that has the proper logic, but nothing on its documentation suggest that it can be used to refine custom types.
It also requires the body of the guard function to be very simple so flow can understand what do you mean. Some type guard function examples may look like this (from flow docs):
function truthy(a, b): boolean %checks {
return !!a && !!b;
}
function isString(y): %checks {
return typeof y === "string";
}
function isNumber(y): %checks {
return typeof y === "number";
}
However when you try a more complex check, for example checking that something is an object, but it is not an array or a date, flow fails to understand your intention and the predicate function will not work. Something like this:
function isObject(obj: mixed): boolean %checks {
return Object.prototype.toString.call(obj) === '[object Object]'
}
Will fail because flow doesn't understand that as a type refinement for object. For that particular case, there is a workaround suggested on a github issue that consist on declaring the function on the type level asserting that it checks for the object type:
declare function isObject(obj: mixed): boolean %checks(obj instanceof Object)
But you can not use that either for your particular case, because you can not do instanceof on a custom type, because it is not a class.
So your options are either go verbose and check all the expected properties are present on a type check, like this:
if (typeof a.x === 'number' && typeof a.y === 'number' && typeof a.z === 'number') {
const {x: ax, y: ay, z: az} = a
// now you can safely use the extracted variables
Note you need to extract the props from the object because, any time you call a function flow will invalidate your type refinement and the next line that access a.x will fail.
You can declare your point as a Class, and use the type system checking for instances of that class.
Or you build a validation function that returns either the correct type or null, so flow can understand the type has been refined:
function isCustomType (p: mixed): CustomType | null {
const validated = ((p:any):CustomType)
if (typeof validated.x === 'number' && typeof validated.y === 'number') return validated
return null
}
const validA = isCustomType(a)
if (validA) {
const {x: ax, y: ay} = validA
// do stuff
This has the disadvantage that you need to allocate extra variables just to satisfy the type system, but I think that is a minor problem.
Also, it will not allow flow to validate the isCustomType function for you, because we are doing type casts to basically cheat flow. But given the surface is small and the objective is very focused it should be ok to be able to keep it manually correct.

Inconsistent error while storing a darray into a Shape

I have a shape like this
const type TFileInfo = shape(
'displayName' => string,
'givenName' => string,
'jobTitle' => string,
'businessPhones' => vec<string>
);
private Person::TFileInfo $person;
Now my constructor of the class looks like so
public function __construct(string $apiresponse) { // instance method
$json = \json_decode($response, /* associative = */ true);
TypeAssert\matches<self::TFileInfo>($json);
$this->person = $json; //OFFENDING LINE
$this->person['businessPhones1'] = "";
}
Now strangely the above code does not throw any error .
If I remove the offending line , then the last line throws a compile time error Expected nothing because the field 'businessPhones1' is not defined in this shape type, and this shape type does not allow unknown fields
What am I missing here ? Is there a better way to assign an API response to a typed variable ?
TypeAssert\matches doesn't prove that its argument is the type you specified, in contrast to the behavior of some other built-ins like is_null which are special-cased in the typechecker. Instead, it coerces the argument and returns it, so you need to move your standalone call to the assignment, i.e. $this->person = TypeAssert\matches<self::TFileInfo>($json);.
You might have expected a type error from the $this->person = $json assignment then, but in fact json_decode and some other unsafe built-in PHP functions are special-cased by the typechecker to be bottom types (convertible to anything) so they could be usable at all before type-assert. It remains this way today: see its type definition in the HHVM source, probably for compatibility.
One other interesting point about this case is that $this->person = $json coerces $this->person to a bottom type as well downstream of the binding. To my understanding, this is a specific behavior of the Hack typechecker to do this for a single level of property nesting, yet it preserves the types for properties of properties (the second example has_error):
<?hh // strict
class Box<T> { public function __construct(public T $v) {} }
function no_error<T>(Box<int> $arg): T {
$arg->v = json_decode('');
return $arg->v;
}
function has_error<T>(Box<Box<int>> $arg): T {
$arg->v->v = json_decode('');
return $arg->v->v;
}

Typescript - Nested arrow function typing

I have this code for deferring the execution of a function
export type DeferredFunction<T> = () => T | PromiseLike<T>;
export class Deferrable<T> {
protected df: DeferredFunction<T>;
constructor(df: DeferredFunction<T>) {
this.df = df;
}
public async execute(): Promise<T> {
return this.df();
}
}
export const defer = <T>(df: DeferredFunction<T>): Deferrable<T> => new Deferrable<T>(df);
That works fine and I can run code like
await defer(() => someFunction('foo', 'bar')).execute();
but I what I want to do is type DeferredFunction in a way that I can specify the inner function's signature but I can't get it working. In generic cases the above works but when I want to limit the arguments such that they are specific to a certain type of function I don't have that kind of control.
For clarity, I want to be able to type the inner function's inputs like (as an example)
export type InnerDeferredFunction<T> = (a: string, b: number, c: SomeObjectType) => T | PromiseLike<T>
Any help would be greatly appreciated!
What "inner function" are you talking about? Is it someFunction? If so then the type of DeferredFunction<T> has no handle on it, since it's a function called by the implementation of DeferredFunction<T>. There's no way in TypeScript to specify "a function whose implementation must call a function of type (x: string, y: number, z: boolean) => string". Implementation details are not part of a function's call signature.
The only way I can imagine to begin to approach this would be for DeferredFunction<T> to accept as a parameter the inner function you want to call, along with the list of arguments to call it with. This might not be what you're looking for, but it's the closest that the type system can represent.
Something like this:
export type InnerDeferredFunction<T, A extends any[]> = (...args: A) => T | PromiseLike<T>;
export type ZeroArgDeferredFunction<T> = InnerDeferredFunction<T, []>
Here I'm keeping A generic but you can specify it to some hardcoded list of arguments. I've renamed your DeferredFunction to ZeroArgDeferredFunction to be explicit that it doesn't need arguments.
But now Deferrable needs to know about T and A:
export class Deferrable<T, A extends any[]> {
protected df: ZeroArgDeferredFunction<T>;
constructor(df: InnerDeferredFunction<T, A>, ...args: A) {
this.df = () => df(...args);
}
public async execute(): Promise<T> {
return this.df();
}
}
And you can see that you have to construct one by passing it the inner function and its arguments, and the ZeroArgDeferredFunction is built inside the constructor and is not passed in.
There are different ways to define defer(). It could be a thin wrapper around new Deferrable the way you had it, or you could imagine splitting it up so that the args come first:
export const defer = <A extends any[]>(...args: A) => <T>(
df: InnerDeferredFunction<T, A>): Deferrable<T, A> => new Deferrable<T, A>(df, ...args);
And then you can test it like this:
function someFunction(x: string, y: string) {
return (x + y).length;
}
function anotherFunction(x: number, y: number) {
return (x * y).toFixed()
}
const deferFooBar = defer('foo', 'bar');
await deferFooBar(someFunction).execute(); // okay
await deferFooBar(anotherFunction); // error! string is not assignable to number
Once you call deferFooBar('foo', 'bar'), the returned value will only accept functions that can be safely called with the arguments foo and 'bar'. That means someFunction will be accepted and anotherFunction will be rejected.
Okay, hope that helps; good luck!
Playground link to code

Linq Invalid Cast Exception Same Object Type

I wrote this query and as my understanding of the business rules has improved I have modified it.
In this most recent iteration I was testing to see if indeed I had some redundancy that could be removed. Let me first give you the query then the error.
public List<ExternalForums> GetAllExternalForums(int extforumBoardId)
{
List<ExternalForums> xtrnlfrm = new List<ExternalForums>();
var query = _forumExternalBoardsRepository.Table
.Where(id => id.Id == extforumBoardId)
.Select(ExtForum => ExtForum.ExternalForums);
foreach (ExternalForums item in query)
{
xtrnlfrm.Add(new ExternalForums { Id = item.Id , ForumName = item.ForumName, ForumUrl = item.ForumUrl });
}
return xtrnlfrm;
}
Now in case it isn't obvious the query select is returning List of ExternalForums. I then loop through said list and add the items to another List of ExternalForums object. This is the redundancy I was expecting to remove.
Precompiler was gtg so I ran through it one time to very everything was kosher before refactoring and ran into a strange error as I began the loop.
Unable to cast object of System.Collections.Generic.HashSet
NamSpcA.NamSpcB.ExternalForums to type NamSpcA.NamSpcB.ExternalForums.
Huh? They are the same object types.
So am I doing something wrong in the way I am projecting my select?
TIA
var query = _forumExternalBoardsRepository.Table
.Where(id => id.Id == extforumBoardId)
.Select(ExtForum => ExtForum.ExternalForums);
This query returns IEnumerable<T> where T is type of ExtForum.ExternalForums property, which I would expect to be another collection, this time of ExternalForum. And the error message matches that, saying you have IEnumerable<HashSet<ExternalForums>>.
If you need that collection of collections to be flattened into one big collection of ExternalForums use SelectMany instead:
var query = _forumExternalBoardsRepository.Table
.Where(id => id.Id == extforumBoardId)
.SelectMany(ExtForum => ExtForum.ExternalForums);

Error: None of the 'n' overloads could convert all the argument types

I'm getting the above error, but as far as I can tell I've matched my argument list exactly.
Code:
void lorentzTransform(std::list<point2P1D>& vol, const vector2D& v) {
std::list<point2P1D> temp = std::list<point2P1D>();
for (const point2P1D& pt : vol) {
point2P1D test = lorentzTransform(pt, v); //Error here.
temp.push_back(test);
}
vol.swap(temp);
}
point2P1D lorentzTransform(const point2P1D& pt, const vector2D& vel);
The overload you want to call might not actually visible of the point of calling. The prototype you show must be placed above the other function.
I'm also very worried about that reference return type. I consider it very likely that you return a dangling reference there.

Resources