exported typed functions that return functions should NOT require the returned function to be typed to work in other modules - flowtype

For example if you are using redux-actions and have created the following module definition for it:
declare module 'redux-actions' {
declare type ActionType = string
declare type Action = {
type: ActionType,
payload?: any,
error?: bool,
meta?: any,
}
declare function createAction<T>(
type: string,
payloadCreator?: (...args: Array<T>) => any,
metaCreator?: Function
): (...args: Array<T>) => Action
}
and then you use that function to return a new function like this:
export const selectProfileTab = createAction('SELECT_PROFILE_TAB', (index: number) => {
playSound()
return { index }
})
and then in another file use it incorrectly like this:
selectorProfileTab('someString')
that won't report an error. It seems to be because flow requires annotations at the "boundaries" of modules. Am I correct?
Because the following does work:
export const selectProfileTab: (index: number) => any = createAction('SELECT_PROFILE_TAB', (index: number) => {
playSound()
return { index }
})
Notice I've annotated the returned function. The following will now produce an error:
selectProfileTab('someString')
I'm just trying to get a hold of this and verify this because it's a lot of extra "boilerplate" to annotate those returned functions, especially when it calling selectProfileTab('someString') would correctly produce an error if used in the same file. It makes you think: what's the point in creating module definitions for the redux-actions package which doesn't have them yet if it doesn't provide any/much value since you have to annotate your returned functions anyway. That's quite disappointing. Am I correct in determining that it's a module "boundaries" limitation/requirement with Flow? Are there any ways to get the desired result of not having to type returned functions that you export?

Related

When accessing Document.find().accessibleBy() it should return Document[]

I defined mongoose model using AccessibleRecordModel like that
export const Restaurant = mongoose.model<
IRestaurantDocument, AccessibleRecordModel<IRestaurantDocument>
>('Post', RestaurantSchema);
When I try to use accessibleBy with find TS is saying that find().accessibleBy() returns IRestaurantDocument instead IRestaurantDocument[], so I need to cast types. Code works correct but Typescript types are wrong
findById().accessibleBy() return IRestaurantDocument type witch is correct.
public async getAll(): Promise<IRestaurantDocument[]> {
const ability = defineAbilitiesFor(user);
return Restaurant.find().accessibleBy(ability).populate('logo').exec();
}
"mongoose": "6.4.4"
"#casl/ability": "5.4.4",
"#casl/mongoose": "6.0.0",

Dart won't compile because of unmatching types, 'List<T>' can't be assigned to the parameter type 'List<T> Function()'

The relevant part of the code looks like this:
static final Map<String, List<Provider>> _availableProviders = {};
Provider(this.name, this._requiresKey, this._versions) {
_versions.forEach((version) => {
Provider._availableProviders.putIfAbsent(version, <Provider>[]),
Provider._availableProviders[version].add(this)
});
}
_versions is a set of Strings and when I try and run I receive this error:
lib/src/api/Provider.dart:18:71: Error: The argument type 'List<Provider>' can't be assigned to the parameter type 'List<Provider> Function()'.
- 'List' is from 'dart:core'.
- 'Provider' is from 'package:bible/src/api/Provider.dart' ('lib/src/api/Provider.dart').
Provider._availableProviders.putIfAbsent(version, <Provider>[]),
The argument type 'List<Provider>' can't be assigned to the parameter type 'List<Provider> Function()'
I'm not exactly sure if this error has to do with the notation of the empty list I created or with how I instantiated the map. Any help would be appreciated!
Second parameter of Map's putIfAbsent is function, that returns value to be put, not value itself: https://api.dart.dev/stable/2.10.4/dart-core/Map/putIfAbsent.html
Rewrite your code to something like this:
static final Map<String, List<Provider>> _availableProviders = {};
Provider(this.name, this._requiresKey, this._versions) {
_versions.forEach((version) => {
Provider._availableProviders.putIfAbsent(version, () => <Provider>[]),
Provider._availableProviders[version].add(this)
});
}

Turn Undefined Property Access Into an Error

I noticed I can define a type for a function and accidentally access properties on that function
type FakeType = {}
type aFunc = string => number
const b: aFunc = () => 1
const a: FakeType = b.whatTheHeck // Flow makes "whatTheHeck" any type
Is there a way to make this an error in Flow?
I don't really know why Flow doesn't error on this automatically, but what you can do is declare aFunc as a callable object, rather than just a function, e.g.
type aFunc = {
(string): number,
};
(On flowtype.com/try)

How to declare a flowtype library definition for polymorphic functions

What is the proper way to specify the type definitions a polymorphic method that depending on the parameter types has different return types?
index.js:
// #flow
import {func1} from './lib1';
const s: string = func1('string');
const b: boolean = func1(); // should cause type error but does not!
lib1.js:
export function func1(p) {
return (typeof p === 'string') ? p : 0;
}
defs/lib1.js.flow
// #flow
declare module "lib1" {
declare export function func1(p: string): string;
declare export function func1(_: void): number;
}
.flowconfig:
[libs]
defs/
I would have hoped to received an error message in index.js(4) but flow does not complain!
Yes, the example you gave is how to declare an overloaded function. However, you may want to change the second line to:
declare function myFunc(_: void): number;
Since Flow allows a function to be called with too many arguments (though not for much longer), it may select the second overload even if the function is called with a string. The modification I suggest makes it so the argument must be undefined (which is what is implicitly passed if you just leave off an argument).

TypeScript Defining a hash table of functions

I'm trying to create a definition file for Handlebars, for use with pre-compiled handlebar scripts. Handlebars will put pre-compiled scripts into a string indexed hash table of functions, but I can't figure out or find how this would be defined.
A hypothetical definition would be:
declare module Handlebars {
export var templates: { (model:any) => string; }[index: string];
}
but that's not a valid definition. The definition should work for a call like this:
var myHtml = Handlebars.templates["person-template"]({FNmae: "Eric"});
A definition like this is close:
export var templates: { (model:any) => string; }[];
But that's an array with a numeric index, and it's not the same thing, and VS Intellisense just decides that the functions in the array are any.
What you want to use is an object type with an index signature (see spec section 3.5.3, specifically 3.5.3.3).
declare module Handlebars {
export var templates: {
[s: string]: (model: any) => string;
}
}

Resources