Open
Description
There are some instances where it would be really useful to have a way to define a succession type for an existing tuple. I presumed something like this would work, but unfortunately it does not:
type Prepend <first, rest> = [first, ...rest]
Here an example where something like this is necessary:
type State <values> = {
chunks Array<string>,
parsed: values
}
interface Parser<a, b> {
parse(state: State<a>): Array<State<b>>
}
class VariableParser<a, b> implements Parser<a, [b, ...a]> {
read: string => ?b
name: string
constructor(name: string, read: string => ?b) {
this.name = name
this.read = read
}
parse({ chunks, parsed }: State<a>): Array<State<[b, ...a]>> {
if (chunks.length === 0) {
return []
} else {
const [first, ...rest] = chunks
const value = this.read(first)
if (value != null) {
return [
{
chunks: rest,
parsed: [value, ...parsed]
}
]
} else {
return []
}
}
}
}
Right now only option to do something along those lines requires either usage of trees: so instead of Parser<a, [b, ...a]>
-> Parser<a, [b, a]>
or functions Parser<a, a => b>
but both options lead to unpleasant interfaces to use and really confusing error messages. Here is a complete example to illustrate this case, here is a tiny summary:
const url = "/user/bob/comments/42"
const userCommentParser = segment("user")
.chain(string("name"))
.segment("comments")
.chain(integer("id"))
parseAs(userCommentParser, (name: string, id: number) => ({ name, id }), url)
parseAs(userCommentParser, (name: string, id: string) => ({ name, id }), url) // <- fails due to type mismatch for `id` argument
230: parseAs(userCommentParser, (name: string, id: string) => ({ name, id }), url)
^ function call. Function cannot be called on any member of intersection type
167: <a, out>(parser: Parse<[a, null]>, (a) => out, url: string): ?out,
^ intersection
Activity