Open Raynos opened 10 years ago
I think we've solved this with the |
operator.
We can say that type Either<T> : Error | T
I'm not sure if we support higher kinded types.
type Functor<Box<T>> : {
map: (this: Box<T>, (T) => U) => Box<U>
}
I think it could be possible but no-one has drafted how this would work yet nor is it in the parser.
We can model tuples with foo : [Number, Number]
We can also model complex libraries like
map : (
(
arr: Array<T>,
cb: (T, Number) => Array<U> | U
) => Array<U>) &
(
obj: Object<String, T>,
cb: (T, Number) => U
) => Object<String, U>
jsig currently does not have nullables by default. The only way null is valid is to use type Foo : Number | null
in which case we can infer that the null branch is unhandled.
jsig has nice terse syntax for functions foo : (A, B) => B
with no overloading, there's only one way to define a function.
jsig supports full type aliases with the type Foo : {{some expression}}
syntax. You can give anything a name that may or may not be generic. for example type Foo : String
or type Bar<T> : Array<T>
we use generic syntax like &
to represent intersections. We dont use non composable syntax like an interface
keyword or a specific extends
keyword.
For interesting multiple things you can just do A & B & C
Lack of higher kinded types
we can easily punt by saying that the annotation syntax supports it. the blog post you link uses essentially the same syntax to express their point. Where TS falls down is in their type inference system. Similarly, for jsig, this wouldn't be a syntax issue but an inference issue. I lack the necessary expertise to comment intelligently on what this would entail or what else it might imply for jsig, but I would say that since it is logically sound throughout and straightforward enough for a human to understand what is going on, then this is a scenario we should support. The syntax you propose, wherein you bind the type of this
and say that it has a map
method, seems like a good way to describe a Mappable
.
Failure to Model JS Values
This is the one that gives me pause. JavaScript is so flexible that it's not necessarily possible - or even desirable for our purposes - to model every possible value. As the linked post mentions, using arrays as tuples, or objects as dictionaries, gets tricky to model, especially when you begin adding other constraints such as property names, array lengths, etc. We've added a few of these modelling features into jsig (in every instance, with concrete use cases); I'd be hesitant to add more complex modelling expressiveness and constraints without compelling use cases just in the name of completionism.
Faulty Type System
The linked post brings up the conflation of null
and undefined
and other types. We addressed this a bit in removing nullable syntax (Type?
) in favor of explicit unions (Type | void
), but I think we should think through this further and make sure that we're doing the right thing.
Annoying Type Syntax (Functions)
This is basically the argument made earlier about the JS quirkiness around defining things that are both invokable functions and objects. For all the lipservice paid to first-class functions in JavaScript, functions sure do get a lot of strange separate-casing. Again, I like the solution we came up with to address this explicitly using type unions although I'll mention again that we have a large wart due to union operator associativity
No Type Aliases
well, we have 'em, at least per my reading of the spec and the use of jsig's type
keyword
clunky intersection syntax
agreed, this is basically what we already do
There is an article about "the bad parts of typescript" by @j201 ( http://j201.github.io/posts/2014-08-30-TypeScript-The-Bad-Parts.html ).
I think typescript is a very interesting piece of prior art for jsig just liked jsdoc is. We should ensure that we do not suffer the same faults as predecessors.
I think it's worth a discussion on how to avoid the following problems:
And any other problems that might be common in typescript.