-
Notifications
You must be signed in to change notification settings - Fork 9
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
enforce constraints on implemented functions; start by at least checking their signatures #4
Comments
Very nice idea! I would love to explore even richer constraints, but this seems like a nice first step. For now, I will leave this out of the proposal proper until I get a feeling for its support as-is. |
Personally I would love some manner of more powerful constraints, although after writing an experimental pattern matching library (here) I found that trying to pattern match functions themselves to be pretty futile and gave up leaving just a generic The problem with functions specifically is that there's many valid implementations with different argument lengths thanks to function add(a, b) {
return a + b
}
function add(a, ...[b]) {
return a + b
}
function add(...[a, b]) {
return a + b
}
function add() {
// And we can't forget the old arguments object
return arguments[0] + arguments[1]
} So there's no way at class creation time to validate that sort've thing, however you could definitely make it so that it's runtime checked e.g.: // Supposing some arbitrary fictional syntax
interface Monad {
bind(Function) -> Monad
}
// Checking on the prototype might be too eager as an instance might still be correct
class Fizz implements Monad {
constructor() {
this[Monad.bind] = someInvalidBind
}
}
class Foo implements Monad {
[Mond.bind]() {
return 3
}
}
class Bar implements Monad {
[Monad.bind](func) {
return 'Not a Monad'
}
}
new Fizz() // InterfaceError, object definitely doesn't satisfy the Monad interface at this point
new Foo().bind(3) // InterfaceError, incorrect arguments for method bind under the Monad interface
new Bar().bind(x => x**2) // InterfaceError returned type doesn't satisfy interface Monad How feasible this is I'm not certain but it's probably worth looking into, it definitely doesn't enable arbitrary type-checking, but it might allow things to become incrementally "type" checkable. |
@Jamesernator I was thinking a simple |
Function length is a really really unreliable way of checking things, it breaks with even just a simple decorator for example: function cached(prop) {
...
// This function has length zero
return func(...args) {
...
}
}
protocol Foo {
a(b, c)
}
class Bar implements Foo {
// @cached a(b, c) has length 0 and so would fail the interface
// which seems counter-useful
@cached
a(b, c) {
...
}
} That's why I came up with some other syntax so that'd be more towards the goals of what you actually want to validate which is generally protocols themselves. For example: You care that class Future implements Monad {
[Monad.bind](func) {
}
}
class Future implements Monad {
// Length 0 but it doesn't matter, it's still a valid implementation
[Monad.bind](...args) {
if (args.length === 0 || typeof args[0] !== 'function') {
throw new Error(`Expected a function`)
}
return ...
}
} It's very similar to the anti-pattern of checking if a function is an I made a small couple functions for experimenting with type-based protocols and it seems to work just fine. |
The decorators proposal is Stage 2 AFAIK so I'm not too concerned with interop, but your point is taken @Jamesernator. |
I very much want the ability (totally fine to not do it by default, as in the current proposal) to enforce constraints. Some use cases include "arraylike", but also define a protocol that describes data records - a "data property descriptor" or "accessor property descriptor" protocol, say. One suggestion I'd have is augmenting the syntax inside |
Barring static types, it would be nice to have checks ensuring that if a protocol intends a field to be a method that an implementation at least defines is as a function (preferably of the same length).
The text was updated successfully, but these errors were encountered: