From a64b8f9fd9ba0f1570faa6c77c67ff36c042ddd5 Mon Sep 17 00:00:00 2001 From: Ika Date: Sat, 12 Aug 2017 20:42:23 +0800 Subject: [PATCH] fix(sub-type): should transform correctly (#33) --- src/__tests__/__snapshots__/parse.ts.snap | 3 +- src/__tests__/parse.ts | 2 ++ src/parsers/indexed-access-type.ts | 13 +++------ .../__tests__/__snapshots__/sub-type.ts.snap | 4 ++- src/types/__tests__/mapped-type.ts | 10 +++---- src/types/__tests__/sub-type.ts | 22 +++++++++----- src/types/sub-type.ts | 29 +++++-------------- 7 files changed, 38 insertions(+), 45 deletions(-) diff --git a/src/__tests__/__snapshots__/parse.ts.snap b/src/__tests__/__snapshots__/parse.ts.snap index c07c483..5e2c391 100644 --- a/src/__tests__/__snapshots__/parse.ts.snap +++ b/src/__tests__/__snapshots__/parse.ts.snap @@ -125,7 +125,7 @@ declare const v_object: { readonly [index: number]: any; }; declare const v_sub_1: X[any][\\"abc\\"][123]; -declare const v_sub_2: A.B.C[X[any]][any][any]; +declare const v_sub_2: A.B.C[X[any]][any]; declare const v_tuple: [string, number]; declare const v_typeof_1: typeof X; declare const v_typeof_2: typeof X.Y.Z; @@ -186,5 +186,6 @@ type TP = T | string; type adjust = (fn: (v: T) => U, index: number, array: T[]) => (T | U)[]; declare function x(v: T): T; import xyz = require(\\"xyz\\"); +type X = A[B[C]]; " `; diff --git a/src/__tests__/parse.ts b/src/__tests__/parse.ts index 6ef0e9c..d5f9bfb 100644 --- a/src/__tests__/parse.ts +++ b/src/__tests__/parse.ts @@ -129,6 +129,8 @@ type adjust = (fn: (v: T) => U, index: number, array: T[]) => (T | U)[]; declare function x(v: T): T; import xyz = require('xyz'); + +type X = A[B[C]]; `; it('should return correctly', () => { diff --git a/src/parsers/indexed-access-type.ts b/src/parsers/indexed-access-type.ts index d7de5e1..9f4d155 100644 --- a/src/parsers/indexed-access-type.ts +++ b/src/parsers/indexed-access-type.ts @@ -4,13 +4,8 @@ import { create_sub_type, ISubType } from '../types/sub-type'; export const parse_indexed_access_type = ( node: ts.IndexedAccessTypeNode, -): ISubType => { - const types = [node.objectType, node.indexType]; - while (types[types.length - 1].kind === ts.SyntaxKind.IndexedAccessType) { - const last_type = types[types.length - 1] as ts.IndexedAccessTypeNode; - types.push(last_type.indexType); - } - return create_sub_type({ - types: types.map(parse_native), +): ISubType => + create_sub_type({ + object: parse_native(node.objectType), + index: parse_native(node.indexType), }); -}; diff --git a/src/types/__tests__/__snapshots__/sub-type.ts.snap b/src/types/__tests__/__snapshots__/sub-type.ts.snap index 50b4100..a779132 100644 --- a/src/types/__tests__/__snapshots__/sub-type.ts.snap +++ b/src/types/__tests__/__snapshots__/sub-type.ts.snap @@ -1,3 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should return correctly 1`] = `"any[string][number]"`; +exports[`should return correctly with object 1`] = `"string[any]"`; + +exports[`should return correctly with object and index 1`] = `"any[string][number]"`; diff --git a/src/types/__tests__/mapped-type.ts b/src/types/__tests__/mapped-type.ts index c5bbbf9..f5854e6 100644 --- a/src/types/__tests__/mapped-type.ts +++ b/src/types/__tests__/mapped-type.ts @@ -94,12 +94,10 @@ it('should return correctly with parameter, optional, readonly, type', () => { optional: true, readonly: true, type: create_sub_type({ - types: [ - in_type, - create_general_type({ - name: parameter.name, - }), - ], + object: in_type, + index: create_general_type({ + name: parameter.name, + }), }), }), ), diff --git a/src/types/__tests__/sub-type.ts b/src/types/__tests__/sub-type.ts index 9c8129a..08e091f 100644 --- a/src/types/__tests__/sub-type.ts +++ b/src/types/__tests__/sub-type.ts @@ -2,30 +2,38 @@ import { any_type, number_type, string_type } from '../../constants'; import { emit } from '../../emit'; import { create_sub_type, is_sub_type } from '../sub-type'; -it('should return correctly', () => { +it('should return correctly with object', () => { expect( emit( create_sub_type({ - types: [any_type, string_type, number_type], + object: string_type, }), ), ).toMatchSnapshot(); }); -it('should throw error with types (length < 2)', () => { - expect(() => +it('should return correctly with object and index', () => { + expect( emit( create_sub_type({ - types: [], + object: create_sub_type({ + object: any_type, + index: string_type, + }), + index: number_type, }), ), - ).toThrowError(); + ).toMatchSnapshot(); }); describe('is_sub_type', () => { it('should return correctly', () => { const element = create_sub_type({ - types: [any_type, string_type, number_type], + object: create_sub_type({ + object: any_type, + index: string_type, + }), + index: number_type, }); expect(is_sub_type(element)).toBe(true); }); diff --git a/src/types/sub-type.ts b/src/types/sub-type.ts index 87300c5..60dc704 100644 --- a/src/types/sub-type.ts +++ b/src/types/sub-type.ts @@ -1,6 +1,6 @@ import * as ts from 'typescript'; import { IType } from '../collections'; -import { ElementKind } from '../constants'; +import { any_type, ElementKind } from '../constants'; import { create_element, is_element, @@ -10,7 +10,8 @@ import { import { transform } from '../transform'; export interface ISubTypeOptions extends IElementOptions { - types: IType[]; + object: IType; + index?: IType; } export interface ISubType @@ -28,22 +29,8 @@ export const is_sub_type = (value: any): value is ISubTypeOptions => /** * @hidden */ -export const transform_sub_type = ( - element: ISubType, - path: IElement[], -) => { - const minimum_length_of_types = 2; - if (element.types.length < minimum_length_of_types) { - throw new Error( - `sub_type.types.length should >= ${minimum_length_of_types}`, - ); - } - const types = element.types.map(type => transform(type, path) as ts.TypeNode); - return types - .slice(minimum_length_of_types) - .reduce( - (parent_type, sub_type) => - ts.createIndexedAccessTypeNode(parent_type, sub_type), - ts.createIndexedAccessTypeNode(types[0], types[1]), - ); -}; +export const transform_sub_type = (element: ISubType, path: IElement[]) => + ts.createIndexedAccessTypeNode( + transform(element.object, path) as ts.TypeNode, + transform(element.index || any_type, path) as ts.TypeNode, + );