Maybe I'm seriously missing something, but I'm unable to get rid of a syntax problem with all my classes.
Here is an example :
class Foo {
bar: (x: string, y: number) => string = (xx: string, yy: number) : string => {
// do some stuff...
};
}
Since I'm enforcing type declarations using tslint, ALL my methods are written like this. It's horrible. Having to copy paste the arguments part, renaming the args names between the type declaration and the lambda declaration is soooo painfull.
So : is there a better way to combine type signature and lambda declaration without all the knee jerking ? I sincerely hope I have missed something and hope this is not "by design" ! :)
You need to configure TSLint to enforce types but ignore the type of the functions:
typedef enforces type definitions to exist. Rule options:
"call-signature" checks return type of functions
"parameter" checks type specifier of function parameters
"property-declaration" checks return types of interface properties
"variable-declaration" checks variable declarations
"member-variable-declaration" checks member variable declarations
You can use a file like this one to configure TSLint. And read this to learn more about how to configure it.
Edit:
If you're targeting ES5, you can also do something like this:
var bar = (x: string, y: number) : string => {
// do some stuff...
};
class Foo {
get bar () { return bar; }
}
var test = (new Foo).bar('hello', 3);
Or:
class Foo {
get bar () {
return (xx: string, yy: number): string => {
// do some stuff...
};
}
}
This way the method's context is preserved and it also exists on the prototype. There's also no need to copy the argument types, TSC will infer them.
Related
I'm building a custom directive in which I'm hoping to validate entire input objects. I'm using the INPUT_OBJECT type with the visitInputObject method on SchemaDirectiveVisitor extended class.
Every time I run a mutation using the input type then visitInputObject does not run.
I've used the other types/methods like visitObject and visitFieldDefinition and they work perfectly. But when trying to use input types and methods they will not trigger.
I've read all the available documentation I can find. Is this just not supported yet?
Some context code(Not actual):
directive #validateThis on INPUT_OBJECT
input MyInputType #validateThis {
id: ID
someField: String
}
type Mutation {
someMutation(myInput: MyInputType!): SomeType
}
class ValidateThisDirective extends SchemaDirectiveVisitor {
visitInputObject(type) {
console.log('Not triggering');
}
}
All the visit methods of a SchemaDirectiveVisitor are ran at the same time -- when the schema is built. That includes visitFieldDefinition and visitFieldDefinition. The difference is that when we use visitFieldDefinition, we often do it to modify the resolve function for the visited field. It's this function that's called during execution.
You use each visit methods to modify the respective schema element. You can use visitInputObject to modify an input object, for example to add or remove fields from it. You cannot use it to modify the resolution logic of an output object's field. You should use visitFieldDefinition for that.
visitFieldDefinition(field, details) {
const { resolve = defaultFieldResolver } = field
field.resolve = async function (parent, args, context, info) {
Object.keys(args).forEach(argName => {
const argDefinition = field.args.find(a => a.name === argName)
// Note: you may have to "unwrap" the type if it's a list or non-null
const argType = argDefinition.type
if (argType.name === 'InputTypeToValidate') {
const argValue = args[argName]
// validate here
}
})
return resolve.apply(this, [parent, args, context, info]);
}
}
I'm trying to create a GraphQL enum type using ApolloStack. But nothing seems to work. For reference, please see the example code.
enum Test {
ABC
Dog
Dog/Cat
}
In the example above, Dog/Cat will cause the server to not work.
I am not sure using '/' is possible when declaring enumeration values.
Try switching the name of 'Dog/Cat' to somthing like 'Animal'
You cannot have a special character in an enum in GraphQL. But you can handle them with a resolver - except there is a gotcha that you cannot resolve a Type in GraphQL, you can only resolve a field of a Type.
For example,
type Foo {
test: Test
}
enum Test {
ABC
Dog
DogCat
}
and in your resolver for Foo,
{
Foo: {
test({ test }) {
// handle special characters and return enum supported string
if (test === "Cat/Dog") return "CatDog";
return test;
}
}
}
Is there a way to use enum default parameters in Haxe? I get this error:
Parameter default value should be constant
enum AnEnum {
A;
B;
C;
}
class Test {
static function main() {
Test.enumNotWorking();
}
static function enumNotWorking(e:AnEnum = AnEnum.A){}
}
Try Haxe link.
Update: this feature has been added in Haxe 4. The code example from the question now compiles as-is with a regular enum.
Previously, this was only possible if you're willing to use enum abstracts (enums at compile time, but a different type at runtime):
#:enum
abstract AnEnum(Int)
{
var A = 1;
var B = 2;
var C = 3;
}
class Test3
{
static function main()
{
nowItWorks();
}
static function nowItWorks(param = AnEnum.A)
{
trace(param);
}
}
There's nothing special about the values I chose, and you could choose another type (string, or a more complex type) if it better suits your use case. You can treat these just like regular enums (for switch statements, etc.) but note that when you trace it at runtime, you'll get "1", not "A".
More information: http://haxe.org/manual/types-abstract-enum.html
Sadly enums can't be used as default values, because in Haxe enums aren't always constant.
This piece of trivia was on the old website but apparently hasn't made it into the new manual yet:
http://old.haxe.org/ref/enums#using-enums-as-default-value-for-parameters
The workaround is to check for a null value at the start of your function:
static function enumNotWorking(?e:AnEnum){
if (e==null) e=AnEnum.A;
}
Alternatively, an Enum Abstract might work for your case.
I have some troubles using union parameters. Imagine I have such a function:
interface IColumnDefinition {
id: string;
title: string;
}
addColumn(definition: string|IColumnDefinition) {
if (typeof (definition) === "string") {
definition = { id: definition, title: definition };
}
var column = new JSColumn(definition);
...
}
I want the user to either pass a complete object that defines a new column, or just pass a string, in which case I create a default object.
However, TypeScript has 2 problems:
definition = { id: definition }; is not allowed, since TypeScript thinks that definition might not be a string - which is wrong, since I make a typeof one line above.
new JSColumn(definition) is not possible, since the constructor requires a IColumnDefinition object, and definition could also be a string - which is also wrong, because the if above made sure that it is always a correct object.
What can I do to convince TypeScript that these are not errors? Is there anything like a cast, which says "Hey, this variable is of type xyz. Trust me, I know what I do."
I'm currently defining the parameter as any, which isn't really an option as I lose the whole advantage of type-checking.
If you want to circumvent the type system of TypeScript you can always use <any> cast.
In this case however there's a better solution:
function addColumn(definition: string | IColumnDefinition) {
var colDef: IColumnDefinition;
if (typeof definition === "string") {
colDef = { id: definition, title: definition };
} else {
colDef = definition;
}
var column = new JSColumn(colDef);
// ...
}
Another option, which might be less clear but generates a smaller JS code:
function addColumn(definition: string | IColumnDefinition) {
var column = new JSColumn(
(typeof definition === "string")
? { id: definition, title: definition }
: definition);
// ...
}
I have Domain class and in that for a particular field of type String, it accepts alphanumeric values,i need a validation in the format it should accept only AB12-QW-1 (or) XY-12 values. how can i validate the field.
Please suggest the solution.
Thanks.
Assume your domain class looks like this
class Foo {
String bar
}
If you can define a regex that matches only the legal values, you can apply the constraint using:
class Foo {
String bar
constraints = {
bar(matches:"PUT-YOUR-REGEX-HERE")
}
}
Alternatively, if you can easily list all the legal values, you can use:
class Foo {
String bar
constraints = {
bar(inList:['AB12-QW-1', 'XY-12'])
}
}
If neither of these solutions will work, then you'll likely need to write a custom validator method
You could use a custom validator:
class YourDomain {
String code
static constraints = {
code( validator: {
if( !( it in [ 'AB12-QW-1', 'XY-12' ] ) ) return ['invalid.code']
})
}
}
However, your explanation of what codes are valid is a bit vague, so you probably want something else in place of the in call
[edit]
Assuming your two strings just showed placeholders for letters or numbers, the following regexp validator should work:
constraints = {
code( matches:'[A-Z]{2}[0-9]{2}-[A-Z]{2}-[0-9]|[A-Z]{2}-[0-9]{2}' )
}
And that will return the error yourDomain.code.matches.invalid if it fails