diff --git a/packages/types/src/checkTypes.manual.ts b/packages/types/src/checkTypes.manual.ts index 0fc3d87bf6..6e001f88e0 100644 --- a/packages/types/src/checkTypes.manual.ts +++ b/packages/types/src/checkTypes.manual.ts @@ -41,8 +41,14 @@ assert(bb.toHuman(), 'All ok'); const ee = registry.createType('Vec>>'); // Option const vb = registry.createType('Option< Vec< u8 > >'); +// nested vecs +const vv = registry.createType('Vec< Vec< Vec< Vec> > >'); +// vec with tuple +const vt = registry.createType('Vec<(u8, u16)>'); +// nested stuff from all-over +const vn = registry.createType('Vec<(u32, (u32, u64), Vec, Vec<(u32, u64)>, [u8;32], [u128;32])>'); -assert(ee[0].unwrap().unwrap().divn(123) && vb.unwrap().bitLength(), 'All ok'); +assert(ee[0].unwrap().unwrap().divn(123) && vb.unwrap().bitLength() && vv.toHuman() && vn.toHuman() && vt.toHuman(), 'All ok'); // Should end up as Raw const gg = registry.createType('[ u8 ;678]'); @@ -62,5 +68,13 @@ const tt2 = registry.createType('( u32 )'); const tt4 = registry.createType('(u8,u16,u32,u64,u128,u256,Break,u256,u128,u64,u32,u16,u8)'); // empty const tt5 = registry.createType('()'); +// nested tuples +const tt6 = registry.createType('(u8, (u16, (u32, u64, u32)), (u64, u64))'); +// more nested tuples +const tt7 = registry.createType('(((u8, u8), (u8, u8)), u16)'); +// nested tuples with a wrapper +const tt8 = registry.createType('(u8, Vec<(u16, u32)>, Option<(u128, u128)>)'); +// same example as above +const tt9 = registry.createType('(u32, (u32, u64), Vec, Vec<(u32, u64)>, [u8;32], [u128;32])'); -assert(tt1[2].bitLength() && tt2.bitLength() && tt4[3].bitLength() && tt5.isEmpty, 'All ok'); +assert(tt1[2].bitLength() && tt2.bitLength() && tt4[3].bitLength() && tt5.isEmpty && tt6[1].toHuman() && tt7.toHuman() && tt8.toHuman() && tt9.toHuman(), 'All ok'); diff --git a/packages/types/src/types/detect.ts b/packages/types/src/types/detect.ts index 86d49a7ed6..ae55e5312f 100644 --- a/packages/types/src/types/detect.ts +++ b/packages/types/src/types/detect.ts @@ -13,15 +13,14 @@ export type DetectConstructor = Constructor<_ // trim leading and trailing spaces export type Trim = - K extends ` ${infer X}` + K extends ` ${infer X} ` | ` ${infer X}` | `${infer X} ` ? Trim - : K extends `${infer X} ` - ? Trim - : K; + : K; -export type __Expand = __Internal, T>; +export type __Wrappers = 'Compact' | 'Option' | 'Vec'; -export type __Internal = +export type __Expand = __ExpandImpl, T>; +export type __ExpandImpl = K extends keyof InterfaceTypes ? InterfaceTypes[K] : T extends ICompact | IEnum | INumber | IOption | IStruct | ITuple | IU8a | IVec @@ -29,46 +28,79 @@ export type __Internal = : __Unwrap; // ensure whatever we wrap is always Compact-capable -export type __Compact = +export type __Compact = __CompactImpl<__Expand>; +export type __CompactImpl = T extends INumber ? Compact : never; -export type __Params = - X extends `${infer A},${infer B}` - ? [__Expand, ...__Params] - : [__Expand]; +// handle option types +export type __Option = __OptionImpl<__Expand>; +export type __OptionImpl = + T extends Codec + ? Option + : never; -export type __Tuple = +export type __Params = __ParamsImpl>; +export type __ParamsImpl = + X extends `Vec<${infer A}>,${infer B}` + ? [__Vec, ...__Params] + : X extends `Option<${infer A}>,${infer B}` + ? [__Option, ...__Params] + : X extends `Vec<${infer A}>` + ? [__Vec] + : X extends `Option<${infer A}>` + ? [__Option] + : X extends `${infer A},${infer B}` + ? __ParamsTuple + : [__ParamsExpand]; +export type __ParamsTuple = __ParamsTupleImpl, Trim>; +export type __ParamsTupleImpl = + B extends `(${infer C}),${infer D}` + ? [__ParamsExpand, __Tuple, ...__Params] + // eslint-disable-next-line @typescript-eslint/no-unused-vars + : B extends `[${infer C}]` | `(${infer C})` + ? [__ParamsExpand, __Expand] + : [__ParamsExpand, ...__Params]; +export type __ParamsExpand = __ParamsExpandImpl>; +export type __ParamsExpandImpl = + // flatten nested tuples + X extends `(${infer A})` | `(${infer A}` | `${infer A})` + ? __ParamsExpand + : __Expand; + +export type __Tuple = __TupleImpl>; +export type __TupleImpl = // eslint-disable-next-line @typescript-eslint/no-unused-vars X extends `${infer A},${infer B}` ? ITuple<__Params> : __Expand; // vec support with short-circuit for u8 -export type __Vec = - Trim extends 'u8' +export type __Vec = __VecImpl>; +export type __VecImpl = + X extends 'u8' ? Bytes : Vec<__Expand>; // fixed vec support -export type __VecFixed = - // eslint-disable-next-line @typescript-eslint/no-unused-vars - X extends `${infer Y};${infer _}` - ? Trim extends 'u8' +export type __VecFixed = __VecFixedImpl, L>; +export type __VecFixedImpl = + L extends string + ? X extends 'u8' ? Raw - : VecFixed<__Expand> + : VecFixed<__Expand> : never; export type __Unwrap = K extends `Compact<${infer X}>` - ? __Compact<__Expand> + ? __Compact : K extends `Option<${infer X}>` - ? Option<__Expand> + ? __Option : K extends `Vec<${infer X}>` ? __Vec - : K extends `[${infer X}]` - ? __VecFixed + : K extends `[${infer X};${infer L}]` + ? __VecFixed : K extends `(${infer X})` ? __Tuple : T;