Last active
October 11, 2022 15:34
-
-
Save luizstacio/b33b62c6c84375081f37ac563a6f6a20 to your computer and use it in GitHub Desktop.
JSON generate typed functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const functions = [ | |
{ | |
name: 'foo', | |
params: [ | |
{ | |
name: 'a', | |
type: 'string', | |
}, | |
{ | |
name: 'b', | |
type: 'number', | |
}, | |
], | |
}, | |
{ | |
name: 'bar', | |
params: [ | |
{ | |
name: 'c', | |
type: 'string', | |
}, | |
{ | |
name: 'd', | |
type: 'number', | |
}, | |
], | |
}, | |
] as const; | |
// Type Decoder from String | |
type TypesMap<T> = T extends 'string' ? string : number; | |
// Union to tuple utilities | |
type TuplePrepend<Tuple extends readonly unknown[], NewElement> = [ | |
NewElement, | |
...Tuple | |
]; | |
type Consumer<Value> = (value: Value) => void; | |
type IntersectionFromUnion<Union> = ( | |
Union extends unknown ? Consumer<Union> : never | |
) extends Consumer<infer ResultIntersection> | |
? ResultIntersection | |
: never; | |
type OverloadedConsumerFromUnion<Union> = IntersectionFromUnion< | |
Union extends unknown ? Consumer<Union> : never | |
>; | |
type UnionLast<Union> = OverloadedConsumerFromUnion<Union> extends ( | |
a: infer A | |
) => void | |
? A | |
: never; | |
type UnionExcludingLast<Union> = Exclude<Union, UnionLast<Union>>; | |
type TupleFromUnionRec< | |
RemainingUnion, | |
CurrentTuple extends readonly unknown[] | |
> = [RemainingUnion] extends [never] | |
? CurrentTuple | |
: TupleFromUnionRec< | |
UnionExcludingLast<RemainingUnion>, | |
TuplePrepend<CurrentTuple, UnionLast<RemainingUnion>> | |
>; | |
type TupleFromUnion<Union> = TupleFromUnionRec<Union, []>; | |
// Array to object function | |
type FuncDec< | |
T extends Array<{ name: string; type: string }>, | |
Args = { | |
[TIndex in T[number] as TypesMap<TIndex['type']>]: boolean; | |
} | |
> = (...args: TupleFromUnion<keyof Args>) => void; | |
type AbiFuncs<T extends ReadonlyArray<{ name: string; params: any }>> = { | |
[I in T[number] as I['name']]: FuncDec<I['params']>; | |
}; | |
// Array to object function | |
const x: AbiFuncs<typeof functions> = {} as any; | |
x.foo('test', 1); | |
// @ts-expect-error | |
x.foo(1, 'test'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also it looks like to re-order the tuple wich leads to issues on the order of arguments