-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add Event3 and Event4 #1
Conversation
Well, basically I think you'd better pass an argument as an object if your event requires more than two parameters, e.g. event(event: 'saveUser'): Event1<MyEventEmitter, {
id: number;
name: string;
age: number;
}>; is much more readable than event(event: 'saveUser'): Event3<MyEventEmitter, number, string, number>; Thus I believe limitting the number of arguments as much as two is reasonable. Is there any special use case in which you want to pass three or four arguments separately rather than passing them as properties of a single object? |
Oh, thx wonderful solution. I had no idea such as. This case is invalid:
But, this case is valid:
The type of So, I think the way is not better way. |
Could you make clear why you think structural subtyping is not useful in some cases? event('saveUser').emit({id: 0, name: 'string', age: 0, extra: 'extra'}); does not raise a runtime error, thus it's natural that TypeScript compiles the code without errors. |
Hmm...? Frankly, I want to throw error in this case:
Because arguments is over supply. If we use optional parameter, using structural subtyping (instead |
Do you mean you always do not want to use values of non-primitive types as function arguments if there is no optional argument, or you are discussing about some special cases? If the former is the case, you have to make most of your functions accept only primitive types, which will prevent you from using many useful design patterns as well as an effective object-oriented programming, I'm afraid. If the latter is the case, please provide an example. |
The case, force to receive and catch all of parameters by rollback function. |
Sorry, I cannot understand what you mean in this sentence.
|
Hmm...
Last argument, However, in this case of using Actually, there are some situations excepting through. But, there are not excepting situations, too. |
Well, why do you have to worry about someone might expect an rollback({
error: Error;
message: string;
errorType: ErrorTypeEnum;
callback: Function
}): void {
...
} This is not a matter of structural subtyping. interface MyInterface {
String stringProperty;
}
class MyClass {
public void doSomething(MyInterface arg) {
...
}
} you cannot avoid someone passing an object which implements MyInterface but has extra properties other than However, you can define |
Hmm... Maybe the reason why I cannot understand your mind is my few knowledge about Typescript and English. Interface is structural subtyping.
Sorry for my explaining, I explained with concrete examples on prev comment for helping your understanding. However, it may provide more difficult.
I intend to understand this thinking. And, I think this classes are needed for this library. As a reference, C# (which are program languages I use usually) define for 8 less arguments. And, maybe haskell have been allowed 7. And, there is ternary operations and using some program languages. So, I think proper for |
Actually, TypeScript provides tuple whose length is not limited. So you can define your event as follows. event(name: 'myEvent'): Event1<MyEventEmitter, [number, string, boolean]>; However, this would not fill your requirement because TypeScript tuple accepts an array whose length is longer than defined. I'm not familiar with C# nor Haskell, but I am with Scala, in which maximum length of tuple is 22. val userForm = Form(
mapping( // defining the form data structure
"id" -> number,
"name" -> text,
"age" -> number
)(
(id, name, age) => User(id, name, age), // convert form parameters (as a tuple) to Scala object
(user: User) => Some(user.id, user.name, user.age) // convert Scala object to values (tuple) to be assigned to the form
)
) In this example, the provider and the consumer of a tuple exists very close, and it is quite easy to confirm that each element of the tuple is used as expected. On the other hand, when you use EventEmitter, the dispatchers and the listeners of the event are loosely-coupled.
In this situation, the definition of the event payload should be as declarative as possible, thus event(event: 'saveUser'): Event1<MyEventEmitter, {
id: number;
name: string;
age: number;
}>; is much better than event(event: 'saveUser'): Event3<MyEventEmitter,
number, // id
string, // name
number // age
>; If you use the latter definition, some event dispatcher may assign body weight to the third argument, and some event listener may treat the first argument as age and the third argument as id (comment can be easily ignored sometimes, as a result of "careless mistakes"). |
It's good to know you are a C# person. interface MyInterface
{
String stringProperty;
}
class MyClass
{
public void doSomething(MyInterface arg)
{
// you cannot prevent an object which is an instance of MyInterface but has a property other than stringProperty
// to be passed as an argument of this method
}
} |
TypeScript 1.6.0-beta provides with strict object literal assignment checking functionality, which aims to avoid typo of the keys of optional parameters but would also meet your requirements. |
Oh, sorry. I have no time recently. |
I wanted.