Skip to content

Instantly share code, notes, and snippets.

@benbenbenbenbenben
Created April 17, 2024 08:31
Show Gist options
  • Save benbenbenbenbenben/0a8dd2ffb7726a22e5aa1f9bd1ea061e to your computer and use it in GitHub Desktop.
Save benbenbenbenbenben/0a8dd2ffb7726a22e5aa1f9bd1ea061e to your computer and use it in GitHub Desktop.
type TupleBuilderEx<Constraint = any, Tail extends [...any] = []> = {
items: Tail,
add: TupleBuilderAdd<Constraint, Tail>
}
type TupleBuilderAdd<Constraint, Tail extends [...any] = []> = <Head extends Constraint>(head: Head) => TupleBuilderEx<Constraint, [...Tail, Head]>
const tupleBuilderEx = <Constraint = any, Head extends Constraint = Constraint, Tail extends [...any] = []>(head: Head, tail?: Tail): TupleBuilderEx<Constraint, [...Tail, Head]> => {
return {
items: [...(tail || []), head] as [...Tail, Head],
add: (next) => tupleBuilderEx(next, [...(tail || []), head] as [...Tail, Head])
}
}
const buildTupleBuilder = <Constraint = any>() => {
return {
withAdd: <Add extends string>(name: Add) => {
type ThisTupleBuilder<Tail extends [...any] = []> = (
{
items: Tail
}
) & Add extends string ? {
[key in Add]: <Head extends Constraint>(head: Head) => ThisTupleBuilder<[...Tail, Head]>
} : never
const add = <Head extends Constraint = Constraint, Tail extends [...any] = []>(head: Head, tail?: Tail): ThisTupleBuilder<[...Tail, Head]> => {
return {
items: [...(tail || []), head] as [...Tail, Head],
[name]: (next: Constraint) => add(next, [...(tail || []), head] as [...Tail, Head])
}
}
return { start: add }
}
}
}
buildTupleBuilder<{ foo: string }>()
.withAdd<"then">("then")
.start({ foo: "", nad: 1 })
.then({foo:"sdsd", v:9})
.then({foo:""})
.items
//^?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment